Чтение вложенного массива и кортежей в JSON в Swift - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть некоторые данные, переданные через JSON, который представляет собой массив кортежей, содержащих массивы, и я не могу извлечь данные из него.Я пытался приводить к разным типам, но единственное, что работает, это [Любой], и я не могу разбить это дальше.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]]]
}

Структура, в которую предполагается войти:

struct WidthRoiPair: Codable {
    let width: Int
    let roi: [Int]
}

Что я хочу сделать (это не работает, воспринимайте это как псевдокод):

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)
}

Попытка p [0] вместо p.0 также не работает, попытка привести JSON напрямую к тому, что мне нужно, что-то вроде этого:

let widthRoiPairsTmp = json["WIDTHS_ROI_PAIRS"] as! [(Int, [Int])]

такжене работаетЯ пытался использовать JSONDecoder (), но я не знаю, как передать ему json ["WIDTHS_ROI_PAIRS"] (или его элементы) (как преобразовать его обратно в данные).Я уверен, что ответ очевиден для любого, кто имеет немного больше опыта работы со Swift, но на данный момент я полностью застрял ...

1 Ответ

0 голосов
/ 28 ноября 2018

Вы можете попробовать

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)
        }
    }
}

Использование

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)
    }
...