我的数据结构看起来像这样。"人类"是一个键字典,其值是人类的字典:
"humans" : {
"abc123" : {
"name" : "Vince",
"pets" : [ {
"animal" : "dog",
"name" : "Clifford"
}, {
"animal" : "fish",
"name" : "Nemo"
} ]
},
"xyz789" : {
"name" : "Jack"
}
}
所以我的 Swift 结构看起来像这样匹配它:
struct Human: Codable {
var name: String!
var pets: [Pet]?
}
struct Pet: Codable {
var name: String!
var animal: Animal!
}
enum Animal: String, Codable {
case cat
case dog
case fish
}
我尝试像这样解码(使用CodableFirebase库(:
let human = try FirebaseDecoder().decode([Human].self, from: value)
但是在尝试对具有某个对象数组的对象进行编码时,我收到以下错误:
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Not a array", underlyingError: nil((
如何将字典的值正确编码为自定义 Swift 对象的数组?
有几个问题:
首先,您犯了一个常见的错误:您忽略了JSON的根对象,该根对象是一个具有一个键humans
的字典。这是试图告诉你的错误。
struct Root : Codable {
let humans : [Human]
}
let human = try FirebaseDecoder().decode(Root.self, from: value)
但是即使添加根结构也不起作用,因为键humans
的值是字典,请注意{}
struct Root : Codable {
let humans : [String:Human]
}
最后,永远不要,永远不要将可解码结构成员声明为隐式解包的可选,它们要么是非可选的(是的,代码编译时没有感叹号(要么是常规可选(?
(
struct Human: Codable {
var name: String
var pets: [Pet]?
}
struct Pet: Codable {
var name: String
var animal: Animal
}
enum Animal: String, Codable {
case cat, dog, fish
}
如果你想要一个Root
结构中的Human
数组而不是字典,你必须编写一个自定义的初始值设定项
struct Root : Codable{
let humans : [Human]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let humanData = try container.decode([String:Human].self, forKey: .humans)
humans = Array(humanData.values)
}
}