为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕容708150 2019-12-17 14:35:58
假设我的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协议实现这一目标?
查看完整描述

3 回答

?
慕哥6287543

TA贡献1831条经验 获得超10个赞

我提出了一个略有不同的解决方案。


假设我们有比简单[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)


查看完整回答
反对 回复 2019-12-17
  • 3 回答
  • 0 关注
  • 674 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信