7

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"
    }
  ]
}
5
  • 1
    You're unlikely to make use of Codable protocol in this case. This is an extremely weird way organize API data. You'd need to parse this out manually from data object. Commented Sep 21, 2019 at 9:38
  • @inokey, agree upon you for the API response, i am finding difficult to parse it. Any other suggestion how to map it, would really help :( Commented Sep 21, 2019 at 9:48
  • 1
    In case you have word on how to organize the API, you could ask a backhander developer to return you a single object. If that's not the case well, you'd need to go a classic way for parsing json objects before Codable protocol was introduced. That'd include serializing Data into the Dictionary and parsing stuff manually by each key. Although if the list of properties could change and miss some of the fields, you'd have a hard time combining stuff into one solid User object anyway. Commented Sep 21, 2019 at 9:52
  • oh, it seems i need to go the classic way, no other option, doesn't seems the efficient way though, to map key and value. thanks for the suggestion. i would like to accept your suggestion if you put it in as answer. Commented Sep 21, 2019 at 10:06
  • Ok, I posted this as an answer. Commented Sep 21, 2019 at 10:19

3 Answers 3

9

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.

Sign up to request clarification or add additional context in comments.

Comments

0

you could try a struct with like this

struct Model: Codable {
    struct User: Codable {
        let key: String
        let value: String
    }
    let singleuser: [User]
}

1 Comment

I don't think that really solves the issue although this is exactly how to parse this json via Codable.
0

Create a struct with 2 variables key and value

public struct UserModel: Codable {
    public struct User: Codable {
        public let key: String
        public let value: String
    }
    public let user: [User]
}

After that using JSONDecoder to decode your string.

func decode(payload: String) {
    do {
        let template = try JSONDecoder().decode(UserModel.self, from: payload.data(using: .utf8)!)
    } catch {
       print(error)
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.