在Swift 4中将字典解码为数组

时间:2018-08-31 03:25:07

标签: firebase firebase-realtime-database swift4 codable

我的数据结构如下所示。 “人类”是键的字典,其值是人类的字典:

  "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:“不是数组”,底层错误:nil))

如何将字典中的值正确编码为自定义Swift对象的数组?

1 个答案:

答案 0 :(得分:1)

有几个问题:

首先,您犯了一个常见错误:您忽略了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
}

如果要在Human结构中使用Root数组而不是字典,则必须编写自定义初始化程序

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)
    }
}