Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing Array of dictionaries in Swift using Codable

I have a JSON response from an API and I cannot figure out how to convert it into an user object (a single user) using Swift Codable. This is the JSON (with some elements removed for ease of reading):

{
  "user": [
    {
      "key": "id",
      "value": "093"
    },
    {
      "key": "name",
      "value": "DEV"
    },
    {
      "key": "city",
      "value": "LG"
    },
    {
      "key": "country",
      "value": "IN"
    },
    {
      "key": "group",
      "value": "OPRR"
    }
  ]
}
like image 738
Vinaykrishnan Avatar asked Sep 21 '19 09:09

Vinaykrishnan


1 Answers

You could do it in two steps if you want to. First declare a struct for the received json

struct KeyValue: Decodable {
    let key: String
    let value: String
}

Then decode the json and map the result into a dictionary using the key/value pairs.

do {
    let result = try JSONDecoder().decode([String: [KeyValue]].self, from: data)

    if let array = result["user"] {
        let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value}

Then encode this dictionary into json and back again using a struct for User

struct User: Decodable {
    let id: String
    let name: String
    let group: String
    let city: String
    let country: String
}

let userData = try JSONEncoder().encode(dict)
let user = try JSONDecoder().decode(User.self, from: userData)

The whole code block then becomes

do {
    let decoder = JSONDecoder()
    let result = try decoder.decode([String: [KeyValue]].self, from: data)

    if let array = result["user"] {
        let dict = array.reduce(into: [:]) { $0[$1.key] = $1.value}
        let userData = try JSONEncoder().encode(dict)
        let user = try decoder.decode(User.self, from: userData)
        //...
    }
} catch {
    print(error)
}

A bit cumbersome but no manual key/property matching is needed.

like image 144
Joakim Danielson Avatar answered Oct 25 '22 01:10

Joakim Danielson