I have some data passed via JSON which is an array of tuples containing arrays, and I can't extract the data out of it. I've tried to cast to different types, but the only thing that works is [Any] and I can't break that down further. The JSON:
{
...
// stuff that I can easily read, like "WIDTH": 33,
...
"WIDTHS_ROI_PAIRS": [[80, [0,0,200,160]], [145, [0, 240, 100, 60]], [145, [100, 240, 100, 60]]]
}
The struct it is meant to go into:
struct WidthRoiPair: Codable {
let width: Int
let roi: [Int]
}
What I want to do (it doesn't work, take it as pseudo-code):
let widthRoiPairsTmp = json["WIDTHS_ROI_PAIRS"] as! [Any]
for p in widthRoiPairsTmp {
let pair = WidthRoiPair(width: p.0 as! Int, roi:p.1 as! [Int])
widthRoiPairs.append(pair)
}
Trying p[0] instead of p.0 also doesn't work, trying to cast the JSON directly to what I need, something like this:
let widthRoiPairsTmp = json["WIDTHS_ROI_PAIRS"] as! [(Int, [Int])]
also doesn't work. I tried to use JSONDecoder() but I don't know how to pass json["WIDTHS_ROI_PAIRS"] (or its elements) to it (how to convert it back to Data). I'm sure the answer is obvious to anyone with a little more experience with Swift, but at the moment I'm totally stuck...
You can try
struct Root: Codable {
let widthsRoiPairs: [[InnerItem]]
enum CodingKeys: String, CodingKey {
case widthsRoiPairs = "WIDTHS_ROI_PAIRS"
}
}
enum InnerItem: Codable {
case integer(Int)
case integerArray([Int])
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode([Int].self) {
self = .integerArray(x)
return
}
throw DecodingError.typeMismatch(InnerItem.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for InnerItem"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .integerArray(let x):
try container.encode(x)
}
}
}
Usage
let str = """
{
"WIDTHS_ROI_PAIRS": [[80, [0,0,200,160]], [145, [0, 240, 100, 60]], [145, [100, 240, 100, 60]]]
}
"""
do {
let res = try JSONDecoder().decode(Root.self, from: str.data(using: .utf8)!)
res.widthsRoiPairs.forEach {
$0.forEach {
switch $0 {
case .integer(let w) :
print(w)
case .integerArray(let arr) :
print(arr)
}
}
}
}
catch {
print(error)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With