您可以编写一个充当CodingKeys对象的自定义结构,并使用字符串对其进行初始化,以便提取您指定的键:
复制代码 private struct CK : CodingKey {
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
var intValue: Int?
init?(intValue: Int) {
return nil
}
}
因此,一旦知道所需的键是什么,就可以说(在"categoryName"
中覆盖:
复制代码 let key =
let con2 = try ! decoder.container(keyedBy: CK.self )
self .unknown = try ! con2.decode([Inner].self , forKey: CK(stringValue:key)!)
因此,我最终要做的是从解码器中创建两个容器-一个使用标准CodingKeys枚举来提取"categoryName"
密钥的值,另一个使用CK结构来提取我们刚刚学到的密钥的值:
复制代码 init(from decoder: Decoder) throws {
let con = try ! decoder.container(keyedBy: CodingKeys.self )
self .categoryName = try ! con.decode(String.self , forKey:.categoryName)
let key = self .categoryName
let con2 = try ! decoder.container(keyedBy: CK.self )
self .unknown = try ! con2.decode([Inner].self , forKey: CK(stringValue:key)!)
}
那么,这就是我的整个“可分解的”结构:
复制代码 struct ResponseData : Codable {
let categoryName : String
let unknown : [Inner]
struct Inner : Codable {
let category : String
let trailerPrice : String
let isFavourit : String ?
let isWatchList : String ?
}
private enum CodingKeys : String , CodingKey {
case categoryName
}
private struct CK : CodingKey {
var stringValue: String
init?(stringValue: String ) {
self.stringValue = stringValue
}
var intValue: Int?
init?(intValue: Int) {
return nil
}
}
init(from decoder: Decoder) throws {
let con = try ! decoder.container(keyedBy: CodingKeys.self)
self.categoryName = try ! con.decode(String .self, forKey :.categoryName)
let key = self.categoryName
let con2 = try ! decoder.container(keyedBy: CK.self)
self.unknown = try ! con2.decode([Inner].self, forKey : CK(stringValue:key)!)
}
}
这是测试床:
复制代码 let json = "" "
[
{
" categoryName": " Trending",
" Trending": [
{
" category": " Trending",
" trailerPrice": " ",
" isFavourit": null,
" isWatchlist": null
}
]
},
{
" categoryName": " Comedy",
" Comedy": [
{
" category": " Comedy",
" trailerPrice": " ",
" isFavourit": null,
" isWatchlist": null
}
]
}
]
" ""
let myjson = try! JSONDecoder().decode(
[ResponseData].self,
from: json.data(using: .utf8)!)
print (myjson)
这是print语句的输出,证明我们已正确填充了结构:
复制代码 [JustPlaying.ResponseData(
categoryName: "Trending" ,
unknown: [JustPlaying.ResponseData.Inner(
category: "Trending" ,
trailerPrice: "" ,
isFavourit: nil,
isWatchList: nil)]),
JustPlaying.ResponseData(
categoryName: "Comedy" ,
unknown: [JustPlaying.ResponseData.Inner(
category: "Comedy" ,
trailerPrice: "" ,
isFavourit: nil,
isWatchList: nil)])
]
当然,在现实生活中,毫无疑问我们会进行一些错误处理!
编辑后来我意识到(部分归功于CodeDifferent的回答),我不需要两个容器。 我可以消除CodingKeys枚举,而我的CK结构可以完成所有工作! 它是通用的密钥制定者:
复制代码 init(from decoder: Decoder) throws {
let con = try ! decoder.container(keyedBy: CK.self )
self .categoryName = try ! con.decode(String.self , forKey:CK(stringValue:"categoryName" )!)
let key = self .categoryName
self .unknown = try ! con.decode([Inner].self , forKey: CK(stringValue:key)!)
}