// // MPPositive_JsonSearchResults.swift // MusicPlayer // // Created by Mr.Zhou on 2024/5/12. // import UIKit //MARK: - 搜索结果结构 ///搜索预览结果结构 struct JsonSearchPreviewResults: 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? ///菜单操作(某些情况下flexColumns无法拿到playListId) let menu:Menu? ///最佳结果组头标题 let header:Header? ///最佳结果其他内容,第0位是无用数据,获取时跳过 let contents:[Content]? enum CodingKeys: String, CodingKey { case thumbnail = "thumbnail" case title = "title" case subtitle = "subtitle" case menu = "menu" 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) menu = try values.decodeIfPresent(Menu.self, forKey: .menu) 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? let browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs? enum CodingKeys: String, CodingKey { case browseId = "browseId" case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseId = try values.decodeIfPresent(String.self, forKey: .browseId) browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs) } struct BrowseEndpointContextSupportedConfigs: Codable { let browseEndpointContextMusicConfig:BrowseEndpointContextMusicConfig? enum CodingKeys: String, CodingKey { case browseEndpointContextMusicConfig = "browseEndpointContextMusicConfig" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig) } struct BrowseEndpointContextMusicConfig: Codable { let pageType:String? enum CodingKeys: String, CodingKey { case pageType = "pageType" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) pageType = try values.decodeIfPresent(String.self, forKey: .pageType) } } } } } } } ///最佳结果副标题 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 Menu: Codable { let menuRenderer:MenuRenderer? enum CodingKeys: String, CodingKey { case menuRenderer = "menuRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) menuRenderer = try values.decodeIfPresent(MenuRenderer.self, forKey: .menuRenderer) } struct MenuRenderer: Codable { let items:[Item]? enum CodingKeys: String, CodingKey { case items = "items" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) items = try values.decodeIfPresent([Item].self, forKey: .items) } struct Item: Codable { let menuNavigationItemRenderer:MenuNavigationItemRenderer? enum CodingKeys: String, CodingKey { case menuNavigationItemRenderer = "menuNavigationItemRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) menuNavigationItemRenderer = try values.decodeIfPresent(MenuNavigationItemRenderer.self, forKey: .menuNavigationItemRenderer) } struct MenuNavigationItemRenderer: Codable { let navigationEndpoint:NavigationEndpoint? enum CodingKeys: String, CodingKey { case navigationEndpoint = "navigationEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint) } struct NavigationEndpoint: Codable { let watchEndpoint:WatchEndpoint? enum CodingKeys: String, CodingKey { case watchEndpoint = "watchEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint) } struct WatchEndpoint: Codable { let playlistId:String? enum CodingKeys: String, CodingKey { case playlistId = "playlistId" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) playlistId = try values.decodeIfPresent(String.self, forKey: .playlistId) } } } } } } } ///最佳结果组头 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:RootMusicResponsiveListItemRenderer? enum CodingKeys: String, CodingKey { case musicResponsiveListItemRenderer = "musicResponsiveListItemRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicResponsiveListItemRenderer = try values.decodeIfPresent(RootMusicResponsiveListItemRenderer.self, forKey: .musicResponsiveListItemRenderer) } } } ///其他结果 struct MusicShelfRenderer: Codable { ///模块标题 let title:Title? ///模块内容 let contents:[Content]? ///更多内容 let bottomEndpoint:BottomEndpoint? enum CodingKeys: String, CodingKey { case title = "title" case contents = "contents" case bottomEndpoint = "bottomEndpoint" } 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) bottomEndpoint = try values.decodeIfPresent(BottomEndpoint.self, forKey: .bottomEndpoint) } 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:RootMusicResponsiveListItemRenderer? enum CodingKeys: String, CodingKey { case musicResponsiveListItemRenderer = "musicResponsiveListItemRenderer" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) musicResponsiveListItemRenderer = try values.decodeIfPresent(RootMusicResponsiveListItemRenderer.self, forKey: .musicResponsiveListItemRenderer) } } struct BottomEndpoint: Codable { let searchEndpoint:SearchEndpoint? enum CodingKeys: String, CodingKey { case searchEndpoint = "searchEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) searchEndpoint = try values.decodeIfPresent(SearchEndpoint.self, forKey: .searchEndpoint) } struct SearchEndpoint: Codable { ///当前搜索文本 let query:String? ///更多内容参数 let params:String? enum CodingKeys: String, CodingKey { case query = "query" case params = "params" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) query = try values.decodeIfPresent(String.self, forKey: .query) params = try values.decodeIfPresent(String.self, forKey: .params) } } } } } } } } } } } }