使用Codable

时间:2018-03-08 16:44:18

标签: json swift codable

我有像这样的json响应

{
  "name":"test",
  "params":{ 
    "param1":"testA", 
    "param2":4055, 
    "param3":9593.34959, 
    "question":"is this is a test?", 
    "anything":"testing?", 
    "random":true
   },
  "price":103.3
}

我的可编码结构看起来像这样

struct:Codable {
    var name:String 
    var params:[String:String]?
    var price:Double
}

我已将params设置为可选,因为有时候没有参数,但很多次都存在并且可编码有问题,因为我不知道params字典中的值是什么类型。我有时甚至不知道钥匙是什么。我只想将它们解析为键和值的字典,其值为Bool,Int,Double或String。所以像这样的词典

let params = ["paramA":1, "param2":"test", "param3":true]

或在上述json的情况下:

let params = ["param1":"testA", "param2":4055, "param3": 9593.34959, "question":"is this is a test?", "anything":"testing?", "random":true]

我很确定我必须创建一个自定义解码器,但不确定如何做到这一点。

1 个答案:

答案 0 :(得分:0)

在你的情况下,手动解码json更容易:

public enum SerializationError: Error {
   case wrongRootElement(String)
   case missing(String)
   case invalid(String, Any)
}
struct YourStruct {
   var name:String
   var params:[String: String]?
   var price:Double
}

extension YourStruct {
   public init(json: Any) throws {
       guard let jsonDict = json as? [String: Any] else {
           throw SerializationError.wrongRootElement("Expected json dictionary not \(json)")
       }
       guard let name = jsonDict["name"] as? String else {
           throw SerializationError.missing("name")
       }
       let params = jsonDict["params"] as? [String: Any]
       let paramsStrs = params?.reduce(into: [String: String]()) { (result, keyValue)  in
           result[keyValue.key] = String(describing: keyValue.value)
       }
       guard let price = jsonDict["price"] as? Double else {
           throw SerializationError.missing("price")
       }
       self.init(name: name, params: paramsStrs, price: price)
    }
}

let anyYourStruct = try? JSONSerialization.jsonObject(with: jsonData, options: [])
let yourStruct = try? YourStruct(json: anyYourStruct)