I have a JSON with the following structure :
"properties":[
{
"name":"Quality",
"values":[],
"displayMode":0,
"type":6
},
{
"name":"Armour",
"values":[],
"displayMode":0,
"type":16
},
{
"name":"Evasion Rating",
"values":[],
"displayMode":0,
"type":17
}
]
The API is always returning an array for "value"
with first element being a String
, and second element being an Int
.
"values":[
[
"+26%",
1
]
],
Here’s how I mapped the JSON so far :
struct Properties: Codable {
var name: String
var values: [Any]
var displayMode: Int
var type: Int
}
At which point Xcode complains because Type 'Properties' does not conform to protocol 'Decodable'
So, I know that Any
doesn't conform to codable
but the thing is I don't how to convert this [Any]
into something Swift can work with...
Can someone share a hint to the solution ?
Thank you very much :)
You need to use an unkeyed container for this when decoding in your custom init(from:)
.
If you know there is always one string followed by one integer you can define the struct for the values like this
struct Value: Decodable {
let string: String?
let integer: Int?
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
string = try container.decodeIfPresent(String.self)
integer = try container.decodeIfPresent(Int.self)
}
}
If there could be more elements you can use a loop instead
struct Value: Decodable {
let strings: [String]
let integers: [Int]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var strings = [String]()
var integers = [Int]()
while !container.isAtEnd {
do {
let string = try container.decode(String.self)
strings.append(string)
} catch {
let integer = try container.decode(Int.self)
integers.append(integer)
}
}
self.integers = integers
self.strings = strings
}
}