'Decode multidimensional unkeyed Json String in Swift
I try to decode a Json String like this:
[
[11,0,"text 1"],
[337,0,"text 2"],
[63,0,"text 3"]
...
]
this is my code to decode:
var stringData: StringData? = nil
do {
let shared = sharedDefaults?.string(forKey: "jsonString")
let decoder = JSONDecoder()
print("xcode: ")
stringData = try decoder.decode(StringData.self, from: shared!.data(using: .utf8)!)
} catch {
print(error)
}
I think I have a wrong structure to decode multidimensional unkeyed array:
struct StringData: Decodable {
//let array: [[String]]
var array: [ArrayData]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
//let firstString = try container.decode([String].self)
array = try container.decode([ArrayData].self)
//array = [firstString, stringArray]
}
struct ArrayData: Decodable {
let id: Int
let cat: Int
let text: String
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
id = try container.decode(Int.self)
cat = try container.decode(Int.self)
text = try container.decode(String.self)
}
}
But I get the error:
debugDescription: "Expected to decode Array<Any> but found a number instead."
What I'm doing wrong?
Solution 1:[1]
You're surprisingly close. Your ArrayData is exactly right. It's not clear why you added StringData; it's not needed. The entire solution is:
let result = try JSONDecoder().decode([ArrayData].self, from: json)
If you do want StringData for some reason, this is what it would look like:
struct StringData: Decodable {
var array: [ArrayData]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var result: [ArrayData] = []
while !container.isAtEnd {
result.append(try container.decode(ArrayData.self))
}
self.array = result
}
}
Solution 2:[2]
The issue is in the init(from decoder:) of StringData
If you want to keep using StringData (I guess there are more complexe data in reality?) you could do this:
var values: [ArrayData] = []
while !container.isAtEnd {
let aValue = try container.decode(ArrayData.self)
values.append(aValue)
}
array = values
Why?
Because the container is an unkeyedContainer, so in the same way you did:
id = try container.decode(Int.self)
cat = try container.decode(Int.self)
text = try container.decode(String.self)
It was iterating on the container.
If StringData is just for show, you can remove it and use [StringData.ArrayData].self while decoding.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rob Napier |
| Solution 2 | Larme |
