如何使用Swift Decodable自定义解码数组的每个元素

时间:2019-01-03 00:10:08

标签: arrays swift decodable

我正在解码天气JSON响应,并且想将信息传递给将对数组进行解码的子解码器。使用Swift Decodable进行解码时,如何为每个JSON数组元素传递此信息?

我正在尝试在最新的Swift版本(4.2)中执行上述操作,并且我已经实现了必要的代码,以成功地自定义解码与数组中使用的模型相同的模型。我无法解码整个数组。

struct DataBlock: Decodable {
    /..
    let weather: [DataPoint]?

    init(from decoder: Decoder) throws {
        try self.init(from: decoder, units: .unit)
    }

    init(from decoder: Decoder, units: Units) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        /..
        let nestedDecoder = try values.superDecoder(forKey: .weather)
        self.weather = try [DataPoint(from: nestedDecoder, units: units)]
    }

    enum CodingKeys: String, CodingKey {
        /..
        case weather
    }
}

在DataPoint模型中:

init(from decoder: Decoder, units: Units) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    /...
    if let value = try values.decodeIfPresent(Double.self, forKey: .value) {
        self.value = Example(value: value, units: units)
    } else {
        self.value = nil
    }
    /..
}

我要解码的JSON结构的相关部分:

"datablock": {
    "weather": [
        {
            /..
            "value": 22.72
            /..
        }
    ]
}

我希望解码器能够通过

units

并手动解码每个数组元素。

但是我收到调试错误:

"Expected to decode Dictionary<String, Any> but found an array instead."

错误在这里触发:

self.weather = try [DataPoint(from: nestedDecoder, units: units)]

1 个答案:

答案 0 :(得分:0)

这通过让我“遍历”每个JSON数组元素并分别解码来解决我的问题:

struct DataBlock: Decodable {
    /..    
    init(from decoder: Decoder, units: Units) throws {
        /..
        var data = [DataPoint]()
        var dataContainer = try values.nestedUnkeyedContainer(forKey: .data)

        while !dataContainer.isAtEnd {
            let nestedDecoder = try dataContainer.superDecoder()
            let dataPoint = try DataPoint(from: nestedDecoder, units: units)
            data.append(dataPoint)
        }

        self.data = data
        /..
    }
    /..
}