Damian Dudycz
Damian Dudycz

Reputation: 2810

Use decodable for custom json decoding

I have a json in such format:

{  
   "route":{  
      "1":"Atrakcyjno\u015b\u0107 przyrodnicza",
      "2":"Atrakcyjno\u015b\u0107 kulturowa",
      "3":"Dla rodzin z dzie\u0107mi",
      "5":"Dla senior\u00f3w",
      "6":"Dla or\u0142\u00f3w",
      "8":"Niepe\u0142nosprawni"
   },
   "apartments":{  
      "1":"WifI",
      "4":"Gastronomia",
      "5":"Parking",
      "6":"Dla niepe\u0142nosprawnych",
      "7":"Dla rodzin z dzie\u0107mi",
      "8":"Dla senior\u00f3w"
   },
   "levels":{  
      "1":"\u0141atwy",
      "2":"\u015aredni",
      "3":"Trudny",
      "4":"Bardzo trudny"
   }
}

I would like to decode it as simple as possible, but I don't know how to decode these sub dictionaries. These are dicts, but it should be array instead. Can I somehow write something, that will make it decode in special way, so that I'll get arrays? So far I have something like this:

struct PreferencesList: Decodable {

    private enum CodingKeys: String, CodingKey {
        case routes     = "route"
        case apartments
        case levels
    }

    let routes:     [Preference]
    let apartments: [Preference]
    let levels:     [Preference]
}

struct Preference: Decodable {
    let id:   Int
    let name: String
}

Upvotes: 2

Views: 94

Answers (1)

Tom
Tom

Reputation: 373

I guess you need to do this step by step.

Keep your struct like it is. Preference doesn't need to be Decodable. Then, override init(from decoder: Decoder) throws function like this.

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let routes = try container.decode([String: String].self, forKey: .routes)
    self.routes = []
    for (key, value) in routes {
        self.routes.append(Preference(id: key, name: value))
    }
    // Do the same for other var...
}

I hope it helps.

Upvotes: 2

Related Questions