2
votes

I have a json response like this

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

My codable struct looks like this

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

I have set params to optional because sometimes there are no params but a lot of times there are and codable has an issue because I don't know what types the values in the params dictionary are. I don't even know what the keys are sometimes. I just want to parse them as a dictionary of keys and values with values of type Bool, Int, Double, or String. so a dict like this

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

or in the case of the above json this:

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

I am pretty sure I have to create a custom decoder but not exactly sure how to do it.

1
stackoverflow.com/a/46049763/4846592 maybe this answer helps :-)heyfrank

1 Answers

0
votes

In your case it's easier to decode json manually like so:

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)