// // MPPositive_JsonSearchResults.swift // MusicPlayer // // Created by Mr.Zhou on 2024/5/12. // import UIKit ///搜索结果结构 struct JsonSearchResults: Codable { let contents:Contents? enum CodingKeys: String, CodingKey { case contents = "contents" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) contents = try values.decodeIfPresent(Contents.self, forKey: .contents) } struct Contents: Codable { let tabbedSearchResultsRenderer:TabbedSearchResultsRenderer? enum CodingKeys: String, CodingKey { case tabbedSearchResultsRenderer = "tabbedSearchResultsRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) tabbedSearchResultsRenderer = try values.decodeIfPresent(TabbedSearchResultsRenderer.self, forKey: .tabbedSearchResultsRenderer) } struct TabbedSearchResultsRenderer: Codable { let tabs:[Tab]? enum CodingKeys: String, CodingKey { case tabs = "tabs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) tabs = try values.decodeIfPresent([Tab].self, forKey: .tabs) } struct Tab:Codable { let tabRenderer:TabRenderer? enum CodingKeys: String, CodingKey { case tabRenderer = "tabRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) tabRenderer = try values.decodeIfPresent(TabRenderer.self, forKey: .tabRenderer) } struct TabRenderer: Codable { let content:Content? enum CodingKeys: String, CodingKey { case content = "content" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) content = try values.decodeIfPresent(Content.self, forKey: .content) } struct Content: Codable { let sectionListRenderer:SectionListRenderer? enum CodingKeys: String, CodingKey { case sectionListRenderer = "sectionListRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) sectionListRenderer = try values.decodeIfPresent(SectionListRenderer.self, forKey: .sectionListRenderer) } struct SectionListRenderer: Codable { ///模块(每个模块内容不一样) let contents:[Content]? enum CodingKeys: String, CodingKey { case contents = "contents" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) contents = try values.decodeIfPresent([Content].self, forKey: .contents) } //MARK: - 模块 struct Content: Codable { ///最佳结果 let musicCardShelfRenderer:MusicCardShelfRenderer? ///其他结果 let musicShelfRenderer:MusicShelfRenderer? enum CodingKeys: String, CodingKey { case musicCardShelfRenderer = "musicCardShelfRenderer" case musicShelfRenderer = "musicShelfRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicCardShelfRenderer = try values.decodeIfPresent(MusicCardShelfRenderer.self, forKey: .musicCardShelfRenderer) musicShelfRenderer = try values.decodeIfPresent(MusicShelfRenderer.self, forKey: .musicShelfRenderer) } //MARK: - 不同模块携带的内容 ///最佳结果 struct MusicCardShelfRenderer: Codable { ///最佳结果封面 let thumbnail:Thumbnail? ///最佳结果标题(附带单曲ID) let title:Title? ///最佳结果副标题 let subtitle:Subtitle? ///最佳结果组头标题 let header:Header? ///最佳结果其他内容,第0位是无用数据,获取时跳过 let contents:[Content]? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" case title = "title" case subtitle = "subtitle" case header = "header" case contents = "contents" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail) title = try values.decodeIfPresent(Title.self, forKey: .title) subtitle = try values.decodeIfPresent(Subtitle.self, forKey: .subtitle) header = try values.decodeIfPresent(Header.self, forKey: .header) contents = try values.decodeIfPresent([Content].self, forKey: .contents) } ///最佳结果封面 struct Thumbnail: Codable { let musicThumbnailRenderer:MusicThumbnailRenderer? enum CodingKeys: String, CodingKey { case musicThumbnailRenderer = "musicThumbnailRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicThumbnailRenderer = try values.decodeIfPresent(MusicThumbnailRenderer.self, forKey: .musicThumbnailRenderer) } struct MusicThumbnailRenderer: Codable { let thumbnail:Thumbnail? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail) } struct Thumbnail: Codable { let thumbnails:[Thumbnails]? enum CodingKeys: String, CodingKey { case thumbnails = "thumbnails" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnails = try values.decodeIfPresent([Thumbnails].self, forKey: .thumbnails) } struct Thumbnails: Codable { let url:String? enum CodingKeys: String, CodingKey { case url = "url" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) url = try values.decodeIfPresent(String.self, forKey: .url) } } } } } ///最佳结果标题 struct Title: Codable { let runs:[Run]? enum CodingKeys: String, CodingKey { case runs = "runs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) runs = try values.decodeIfPresent([Run].self, forKey: .runs) } struct Run: Codable { ///标题文本 let text:String? let navigationEndpoint:NavigationEndpoint? enum CodingKeys: String, CodingKey { case text = "text" case navigationEndpoint = "navigationEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint) } struct NavigationEndpoint: Codable { ///这个值存在就是音乐单曲 let watchEndpoint:WatchEndpoint? ///这个值存在就是艺术家 let browseEndpoint:BrowseEndpoint? enum CodingKeys: String, CodingKey { case watchEndpoint = "watchEndpoint" case browseEndpoint = "browseEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint) browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint) } struct WatchEndpoint: Codable { let videoId:String? enum CodingKeys: String, CodingKey { case videoId = "videoId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) videoId = try values.decodeIfPresent(String.self, forKey: .videoId) } } struct BrowseEndpoint: Codable { let browseId:String? enum CodingKeys: String, CodingKey { case browseId = "browseId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseId = try values.decodeIfPresent(String.self, forKey: .browseId) } } } } } ///最佳结果副标题 struct Subtitle: Codable { let runs:[Run]? enum CodingKeys: String, CodingKey { case runs = "runs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) runs = try values.decodeIfPresent([Run].self, forKey: .runs) } struct Run: Codable { ///标题文本 let text:String? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) } } } ///最佳结果组头 struct Header: Codable { let musicCardShelfHeaderBasicRenderer:MusicCardShelfHeaderBasicRenderer? enum CodingKeys: String, CodingKey { case musicCardShelfHeaderBasicRenderer = "musicCardShelfHeaderBasicRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicCardShelfHeaderBasicRenderer = try values.decodeIfPresent(MusicCardShelfHeaderBasicRenderer.self, forKey: .musicCardShelfHeaderBasicRenderer) } struct MusicCardShelfHeaderBasicRenderer: Codable { let title:Title? enum CodingKeys: String, CodingKey { case title = "title" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) title = try values.decodeIfPresent(Title.self, forKey: .title) } struct Title:Codable { let runs:[Run]? enum CodingKeys: String, CodingKey { case runs = "runs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) runs = try values.decodeIfPresent([Run].self, forKey: .runs) } struct Run: Codable { ///标题文本 let text:String? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) } } } } } ///最佳结果其他内容 struct Content: Codable { let musicResponsiveListItemRenderer:MusicResponsiveListItemRenderer? enum CodingKeys: String, CodingKey { case musicResponsiveListItemRenderer = "musicResponsiveListItemRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicResponsiveListItemRenderer = try values.decodeIfPresent(MusicResponsiveListItemRenderer.self, forKey: .musicResponsiveListItemRenderer) } struct MusicResponsiveListItemRenderer: Codable { ///封面 let thumbnail:Thumbnail? ///文本内容(第0位是标题,其他拼成副标题) let flexColumns:[FlexColumn]? ///单曲/视频ID(playlistItemData存在说明这条数据单曲/视频) let playlistItemData:PlaylistItemData? ///专辑/歌单ID(navigationEndpoint存在说明这条数据是专辑/歌单) let navigationEndpoint:NavigationEndpoint? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" case flexColumns = "flexColumns" case playlistItemData = "playlistItemData" case navigationEndpoint = "navigationEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail) flexColumns = try values.decodeIfPresent([FlexColumn].self, forKey: .flexColumns) playlistItemData = try values.decodeIfPresent(PlaylistItemData.self, forKey: .playlistItemData) navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint) } struct Thumbnail: Codable { let musicThumbnailRenderer:MusicThumbnailRenderer? enum CodingKeys: String, CodingKey { case musicThumbnailRenderer = "musicThumbnailRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicThumbnailRenderer = try values.decodeIfPresent(MusicThumbnailRenderer.self, forKey: .musicThumbnailRenderer) } struct MusicThumbnailRenderer: Codable { let thumbnail:Thumbnail? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail) } struct Thumbnail: Codable { let thumbnails:[Thumbnails]? enum CodingKeys: String, CodingKey { case thumbnails = "thumbnails" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnails = try values.decodeIfPresent([Thumbnails].self, forKey: .thumbnails) } struct Thumbnails: Codable { let url:String? enum CodingKeys: String, CodingKey { case url = "url" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) url = try values.decodeIfPresent(String.self, forKey: .url) } } } } } struct FlexColumn: Codable { let musicResponsiveListItemFlexColumnRenderer:MusicResponsiveListItemFlexColumnRenderer? enum CodingKeys: String, CodingKey { case musicResponsiveListItemFlexColumnRenderer = "musicResponsiveListItemFlexColumnRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicResponsiveListItemFlexColumnRenderer = try values.decodeIfPresent(MusicResponsiveListItemFlexColumnRenderer.self, forKey: .musicResponsiveListItemFlexColumnRenderer) } struct MusicResponsiveListItemFlexColumnRenderer: Codable { let text:Text? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(Text.self, forKey: .text) } struct Text: Codable { let runs:[Run]? enum CodingKeys: String, CodingKey { case runs = "runs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) runs = try values.decodeIfPresent([Run].self, forKey: .runs) } struct Run: Codable { ///标题文本 let text:String? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) } } } } } struct PlaylistItemData: Codable { let videoId:String? enum CodingKeys: String, CodingKey { case videoId = "videoId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) videoId = try values.decodeIfPresent(String.self, forKey: .videoId) } } struct NavigationEndpoint: Codable { let browseEndpoint:BrowseEndpoint? enum CodingKeys: String, CodingKey { case browseEndpoint = "browseEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint) } struct BrowseEndpoint: Codable { let browseId:String? enum CodingKeys: String, CodingKey { case browseId = "browseId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseId = try values.decodeIfPresent(String.self, forKey: .browseId) } } } } } } ///其他结果 struct MusicShelfRenderer: Codable { ///模块标题 let title:Title? ///模块内容 let contents:[Content]? enum CodingKeys: String, CodingKey { case title = "title" case contents = "contents" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) title = try values.decodeIfPresent(Title.self, forKey: .title) contents = try values.decodeIfPresent([Content].self, forKey: .contents) } struct Title:Codable { let runs:[Run]? enum CodingKeys: String, CodingKey { case runs = "runs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) runs = try values.decodeIfPresent([Run].self, forKey: .runs) } struct Run: Codable { ///标题文本 let text:String? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) } } } struct Content: Codable { let musicResponsiveListItemRenderer:MusicResponsiveListItemRenderer? enum CodingKeys: String, CodingKey { case musicResponsiveListItemRenderer = "musicResponsiveListItemRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicResponsiveListItemRenderer = try values.decodeIfPresent(MusicResponsiveListItemRenderer.self, forKey: .musicResponsiveListItemRenderer) } struct MusicResponsiveListItemRenderer: Codable { ///封面 let thumbnail:Thumbnail? ///文本内容(第0位是标题,其他拼成副标题) let flexColumns:[FlexColumn]? ///单曲/视频ID(playlistItemData存在说明这条数据单曲/视频) let playlistItemData:PlaylistItemData? ///专辑/歌单ID(navigationEndpoint存在说明这条数据是专辑/歌单) let navigationEndpoint:NavigationEndpoint? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" case flexColumns = "flexColumns" case playlistItemData = "playlistItemData" case navigationEndpoint = "navigationEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail) flexColumns = try values.decodeIfPresent([FlexColumn].self, forKey: .flexColumns) playlistItemData = try values.decodeIfPresent(PlaylistItemData.self, forKey: .playlistItemData) navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint) } struct Thumbnail: Codable { let musicThumbnailRenderer:MusicThumbnailRenderer? enum CodingKeys: String, CodingKey { case musicThumbnailRenderer = "musicThumbnailRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicThumbnailRenderer = try values.decodeIfPresent(MusicThumbnailRenderer.self, forKey: .musicThumbnailRenderer) } struct MusicThumbnailRenderer: Codable { let thumbnail:Thumbnail? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnail = try values.decodeIfPresent(Thumbnail.self, forKey: .thumbnail) } struct Thumbnail: Codable { let thumbnails:[Thumbnails]? enum CodingKeys: String, CodingKey { case thumbnails = "thumbnails" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) thumbnails = try values.decodeIfPresent([Thumbnails].self, forKey: .thumbnails) } struct Thumbnails: Codable { let url:String? enum CodingKeys: String, CodingKey { case url = "url" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) url = try values.decodeIfPresent(String.self, forKey: .url) } } } } } struct FlexColumn: Codable { let musicResponsiveListItemFlexColumnRenderer:MusicResponsiveListItemFlexColumnRenderer? enum CodingKeys: String, CodingKey { case musicResponsiveListItemFlexColumnRenderer = "musicResponsiveListItemFlexColumnRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicResponsiveListItemFlexColumnRenderer = try values.decodeIfPresent(MusicResponsiveListItemFlexColumnRenderer.self, forKey: .musicResponsiveListItemFlexColumnRenderer) } struct MusicResponsiveListItemFlexColumnRenderer: Codable { let text:Text? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(Text.self, forKey: .text) } struct Text: Codable { let runs:[Run]? enum CodingKeys: String, CodingKey { case runs = "runs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) runs = try values.decodeIfPresent([Run].self, forKey: .runs) } struct Run: Codable { ///标题文本 let text:String? enum CodingKeys: String, CodingKey { case text = "text" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) } } } } } struct PlaylistItemData: Codable { let videoId:String? enum CodingKeys: String, CodingKey { case videoId = "videoId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) videoId = try values.decodeIfPresent(String.self, forKey: .videoId) } } struct NavigationEndpoint: Codable { let browseEndpoint:BrowseEndpoint? enum CodingKeys: String, CodingKey { case browseEndpoint = "browseEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint) } struct BrowseEndpoint: Codable { let browseId:String? enum CodingKeys: String, CodingKey { case browseId = "browseId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseId = try values.decodeIfPresent(String.self, forKey: .browseId) } } } } } } } } } } } } } }