我在使用Codable解码JSON时遇到了大问题
我得到了错误
线程1:致命错误:“尝试!”表达式意外引发错误:Swift.DecodingError.keyNotFound(SpecieKeys(stringValue:“ v”,intValue:nil),Swift.DecodingError.Context(codingPath:[_JSONKey(stringValue:“ Index 0”,intValue:0)],debugDescription :“没有与键SpecieKeys(stringValue:\” v \“,intValue:nil)(\” v \“)。(\” v \“)。”相关联的值,underlyingError:nil))
我花了很多时间,但我不明白为什么..:-(
这是我的json
let myJson = """
[{"i":"4","p":"4","l":["Ail"],"ll":["Allium sativum L."]},
{"i":"20.1","l":["Artichaut"],"ll":["Cynara cardunculus"]},
{"i":"XX.3",
"l":["Tomate cerise"],
"ll":["Solanum humboldtii"],
"v":[{"s":1,
"i":"0",
"l":"Orange Grape Tress",
"c":"Orange",
"h":992,
"ss":12
}]
}]
"""
let jsonDATA = myJson.data(using: .utf8)!
和我的结构
struct Specie : Decodable {
var id : String?
var name : [String]?
var latinName : [String]?
var varieties : [Variety]?
// keys
enum SpecieKeys: String, CodingKey {
case id = "i"
case name = "l"
case latinName = "ll"
case varieties = "v"
}
struct Variety : Decodable {
var source : Int?
var id : String?
var color : String?
var name : String?
var photo : String?
var harvest : Int?
var semiShelter : Int?
var semiOutside : Int?
// keys
enum VarietyKeys: String, CodingKey {
case id = "i"
case source = "s"
case color = "c"
case photo = "p"
case harvest = "h"
case semiShelter = "ss"
case semiOutside = "so"
case name = "l"
}
init(from decoder: Decoder) throws
{
let vValues = try decoder.container(keyedBy: VarietyKeys.self)
id = try vValues.decode(String.self, forKey: .id)
source = try vValues.decode(Int.self, forKey: .source)
name = try vValues.decode(String.self, forKey: .name)
color = try vValues.decode(String.self, forKey: .color)
photo = try vValues.decode(String.self, forKey: .photo)
harvest = try vValues.decode(Int.self, forKey: .harvest)
semiShelter = try vValues.decode(Int.self, forKey: .semiShelter)
semiOutside = try vValues.decode(Int.self, forKey: .semiOutside)
}
}
init(from decoder: Decoder) throws
{
let sValues = try decoder.container(keyedBy: SpecieKeys.self)
id = try sValues.decode(String.self, forKey: .id)
name = try sValues.decode(Array<String>.self, forKey: .name)
latinName = try sValues.decode(Array<String>.self, forKey: .latinName)
varieties = try sValues.decode(Array<Variety>.self, forKey: .varieties)
}
}
最后一个代码
var jsonResult = [Specie]()
jsonResult = try! JSONDecoder().decode(Array<Specie>.self, from: jsonDATA)
有人可以帮助我解决我的错误。
答案 0 :(得分:2)
对于每个可选值,您必须使用decodeIfPresent(:forKey) 而不是decode( :forKey)。 decode(_:forKey)
在找到nil
值("No value associated with key ..."
)时将无法解析
但是,更简单的解决方案是让编译器生成您的解码初始化程序:
struct Specie : Decodable {
var id : String?
var name : [String]?
var latinName : [String]?
var varieties : [Variety]?
// keys
enum CodingKeys: String, CodingKey {
case id = "i"
case name = "l"
case latinName = "ll"
case varieties = "v"
}
struct Variety : Decodable {
var source : Int?
var id : String?
var color : String?
var name : String?
var photo : String?
var harvest : Int?
var semiShelter : Int?
var semiOutside : Int?
// keys
enum CodingKeys: String, CodingKey {
case id = "i"
case source = "s"
case color = "c"
case photo = "p"
case harvest = "h"
case semiShelter = "ss"
case semiOutside = "so"
case name = "l"
}
}
}
唯一需要做的就是将您的键枚举重命名为CodingKeys
,以便编译器可以识别它们。