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

Time:01-28

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!

CodePudding user response:

Create a custom decoder. 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)}
    }
}
  • Related