Reputation: 369
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
Upvotes: 2
Views: 178
Reputation: 236448
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")]
Upvotes: 0
Reputation: 4259
With Swifts structs combined with Codable we can achieve very clean and nice solution to the problem.
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
}
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)
}
Upvotes: 1
Reputation: 52013
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)
}
Upvotes: 0
Reputation: 33967
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"]!) } }
Upvotes: 0