【问题标题】:Decoding JSON with variable parameters using Codable使用 Codable 解码带有可变参数的 JSON
【发布时间】:2018-08-17 02:36:11
【问题描述】:

我有一个这样的 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 设置为 optional,因为有时没有 params,但很多时候有并且 codable 存在问题,因为我不知道 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]

我很确定我必须创建一个自定义解码器,但不完全确定如何去做。

【问题讨论】:

标签: json swift codable


【解决方案1】:

在您的情况下,像这样手动解码 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)

【讨论】:

  • 我想了这么多,然后继续使用 swiftyjson 来做一些类似于你在这里写的事情。感谢您的帮助!
  • 另一种方法是if let stringValue = try? container.decode(String.self, forkey: .abc) { } else if let intValue = try? container.decode(Int.self, forkey: .abc) ...
猜你喜欢
  • 2021-10-15
  • 2018-02-27
  • 2018-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多