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?
CodePudding user response:
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
}
}
CodePudding user response:
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.