Search code examples
jsonswiftparsingcodabledecodable

Parse JSON as array of objects instead of dictionary using Codable in Swift


I receive the following JSON from API

{
   "someProperty":"someValue",
   "type":"type1",
   "values":{
      "first":"someValue",
      "second":"someValue" // keys and values are always different !
   }
}

I created model to parse this JSON and it works.

struct MyModel: Codable {
    let someProperty: String
    let type: SomeType
    var values: [String: String]?
}

enum SomeType: Codable {
    case type1, type2
}

But I need to get array of objects instead of dictionary. Because I need to get values in right order.

I want something like this:

struct MyModel: Codable {
    let someProperty: String
    let type: SomeType
    var values: [Value]?
}

enum SomeType: Codable {
    case type1, type2
}

struct Value: Codable {
    let key: String
    let value: String
}

And I don't understand what should I change in my code to make this model works. Because now I get error "Expected to decode Array but found a dictionary instead."

Is there a way to parse JSON like I want? Any suggestions? Maybe example of code with similar parsing

Thanks for your time and your help!


Solution

  • Create a custom init. In it decode the dictionary and map it into an array of your Value:

    struct MyModel: Codable {
        let someProperty: String
        let type: SomeType
        var values: [Value]?
    
        enum CodingKeys: CodingKey{
            case someProperty, type, values
        }
        
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            
            someProperty = try container.decode(String.self, forKey: .someProperty)
            type = try container.decode(SomeType.self, forKey: .type)
            
            let dictionary = try container.decodeIfPresent([String:String].self, forKey: .values)
            values = dictionary?.map{Value(key: $0.key, value: $0.value)}
        }
    }