skip to Main Content

I need your help on decoding this piece of JSON

{
    "json": {
        "firstItem": {
            "key": "key",
            "value": "data"
        },
        "secondItem": {
            "key": "key",
            "value": "data"
        },
        "thirdItem": {
            "key": "key",
            "value": "data"
        },.......... //All of the data, which is a lot, comes like this
    }
}

I want to be able to decode this data, but can’t figure out a way without having to write too much code because there are a lot of items. Is it possible to be able to decode this JSON maybe into a nesting of dictionaries, or even better into an array of item objects with just key and value attributes? Thanks in advance

4

Answers


  1. With Swifts structs combined with Codable we can achieve very clean and nice solution to the problem.

    Declare Item struct

    helper struct will be useful when retrieving values from each item contained within the json dictionary

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

    Decode the JSON

    now, considering the json is a string value, you can decode it easily with JSONDecoder

    let jsonString: String // your json here
    
    guard let data = jsonString.data(using: .utf8) else { return }
    let decoder = JSONDecoder()
    do {
        let decoded = try decoder.decode([String: [String: Item]].self, from: data)
        let itemsDict: [String: Item] = decoded["json"] ?? [:]
    
        // do what you want with the items!
        let firstItem: Item? = itemsDict["firstItem"]
        let items: [Item] = itemsDict.values
    } catch {
        print(error)
    }
    
    Login or Signup to reply.
  2. I went old school with my answer:

    guard let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: [String: [String: Any]]] else { return }
    let keyValues = json["json"].map { $0.values.map { ($0["key"]! as! String, $0["value"]!) } }
    
    Login or Signup to reply.
  3. Create a custom type for your key/value pairs

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

    and then decode them into an array like this

    do {
        let result = try JSONDecoder().decode([String: [String: KeyValue]].self, from: data)
        let array = result["json"]?.reduce(into: []) { $0.append($1.value) }
    } catch {
        print(error)
    }
    
    Login or Signup to reply.
  4. If you don’t know the keys of the nesting json you can simply decode it as a dictionary of items:

    struct Root: Decodable {
        let json: [String: Item]
    }
    

    struct Item: Decodable {
        let key, value: String
    }
    

    let json = """
    {
        "json": {
            "firstItem": {
                "key": "key",
                "value": "data"
            },
            "secondItem": {
                "key": "key",
                "value": "data"
            },
            "thirdItem": {
                "key": "key",
                "value": "data"
            }
        }
    }
    """
    

    do {
        let items = try JSONDecoder().decode(Root.self, from: .init(json.utf8)).json.map(.value)
        print(items)
    } catch {
        print(error)
    }
    

    This will print:

    [Item(key: "key", value: "data"), Item(key: "key", value: "data"), Item(key: "key", value: "data")]

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search