Swift 4可解码协议中如何使用JSON字典类型解码属性

假设我的Customer数据类型包含一个metadata属性,该属性可以在客户对象中包含任何JSON字典


struct Customer {

  let id: String

  let email: String

  let metadata: [String: Any]

}

{  

  "object": "customer",

  "id": "4yq6txdpfadhbaqnwp3",

  "email": "john.doe@example.com",

  "metadata": {

    "link_id": "linked-id",

    "buy_count": 4

  }

}

该metadata属性可以是任意JSON映射对象。


在我可以从反序列化的JSON强制转换属性(NSJSONDeserialization但使用新的Swift 4 Decodable协议)之前,我仍然想不出一种方法。


有谁知道如何在Swift 4中使用Decodable协议实现这一目标?


慕容708150
浏览 679回答 3
3回答

慕哥6287543

我提出了一个略有不同的解决方案。假设我们有比简单[String: Any]解析还要多的东西:Any可能是数组,嵌套字典或数组字典。像这样:var json = """{  "id": 12345,  "name": "Giuseppe",  "last_name": "Lanza",  "age": 31,  "happy": true,  "rate": 1.5,  "classes": ["maths", "phisics"],  "dogs": [    {      "name": "Gala",      "age": 1    }, {      "name": "Aria",      "age": 3    }  ]}"""好吧,这是我的解决方案:public struct AnyDecodable: Decodable {  public var value: Any  private struct CodingKeys: CodingKey {    var stringValue: String    var intValue: Int?    init?(intValue: Int) {      self.stringValue = "\(intValue)"      self.intValue = intValue    }    init?(stringValue: String) { self.stringValue = stringValue }  }  public init(from decoder: Decoder) throws {    if let container = try? decoder.container(keyedBy: CodingKeys.self) {      var result = [String: Any]()      try container.allKeys.forEach { (key) throws in        result[key.stringValue] = try container.decode(AnyDecodable.self, forKey: key).value      }      value = result    } else if var container = try? decoder.unkeyedContainer() {      var result = [Any]()      while !container.isAtEnd {        result.append(try container.decode(AnyDecodable.self).value)      }      value = result    } else if let container = try? decoder.singleValueContainer() {      if let intVal = try? container.decode(Int.self) {        value = intVal      } else if let doubleVal = try? container.decode(Double.self) {        value = doubleVal      } else if let boolVal = try? container.decode(Bool.self) {        value = boolVal      } else if let stringVal = try? container.decode(String.self) {        value = stringVal      } else {        throw DecodingError.dataCorruptedError(in: container, debugDescription: "the container contains nothing serialisable")      }    } else {      throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not serialise"))    }  }}尝试使用let stud = try! JSONDecoder().decode(AnyDecodable.self, from: jsonData).value as! [String: Any]print(stud)
打开App,查看更多内容
随时随地看视频慕课网APP