JSONDecoder-解码字符串值以更正类型

时间:2018-10-15 18:29:45

标签: swift decodable

我正在使用一个JSON API,该API将每个字段作为字符串返回。但是,其中一些字符串值实际上代表时间戳,经度和纬度(作为单独的字段)。

如果我分别将这些值指定为['AAA', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => ['AAA', 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0] [0, 'AAA', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => ['XXX', 'AAA', 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX'] [0, 0, 'AAA', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] => ['XXX', 0, 'AAA', 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX'] [0, 0, 0, 'AAA', 0, 0, 0, 0, 0, 0, 0, 0, 0] => [0, 'XXX', 0, 'AAA', 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0] [0, 0, 0, 0, 'AAA', 0, 0, 0, 0, 0, 0, 0, 0] => ['XXX', 0, 0, 'XXX', 'AAA', 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX'] [0, 0, 0, 0, 0, 'AAA', 0, 0, 0, 0, 0, 0, 0] => ['XXX', 0, 0, 'XXX', 0, 'AAA', 'XXX', 0, 0, 'XXX', 0, 0, 'XXX'] [0, 0, 0, 0, 0, 0, 'AAA', 0, 0, 0, 0, 0, 0] => [0, 'XXX', 0, 0, 'XXX', 0, 'AAA', 'XXX', 0, 0, 'XXX', 0, 0] [0, 0, 0, 0, 0, 0, 0, 'AAA', 0, 0, 0, 0, 0] => ['XXX', 0, 0, 'XXX', 0, 0, 'XXX', 'AAA', 0, 'XXX', 0, 0, 'XXX'] [0, 0, 0, 0, 0, 0, 0, 0, 'AAA', 0, 0, 0, 0] => ['XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 'AAA', 'XXX', 0, 0, 'XXX'] [0, 0, 0, 0, 0, 0, 0, 0, 0, 'AAA', 0, 0, 0] => [0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 'AAA', 'XXX', 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'AAA', 0, 0] => ['XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 'AAA', 0, 'XXX'] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'AAA', 0] => ['XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 'AAA', 'XXX'] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'AAA'] => [0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 0, 'XXX', 0, 'AAA'] Date,则它会迅速引发错误Double

Expected to decode Double but found a string

我已经看到一些似乎在线处理日期格式的示例,但是我不确定围绕Double值怎么办?

我尝试覆盖Struct Place { var created_at: Date? var longitude: Double? var latitude: Double? } ,但这仍然无法提供正确的值:

例如

init(from decoder:Decoder)

我知道我可以提取字符串并将其转换为类似double的

init(from decoder:Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    longitude = try values.decode(Double.self, forKey: .longitude) //returns nil but using String works fine
}

但是还有另一种方法吗?

此外,我实际上还有许多可以很好转换的其他属性,但是通过对这3个属性进行这种处理,我现在必须在其中添加所有其他属性,这似乎有点多余。有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

如果JSON值为String,则必须解码String。从StringDouble的隐式类型转换是不可能的。

您可以通过添加计算变量coordinate来避免使用自定义初始化程序,在这种情况下,CodingKeys是必需的

import CoreLocation

struct Place : Decodable {

    private enum CodingKeys: String, CodingKey { case createdAt = "created_at", longitude, latitude}

    let createdAt: Date
    let longitude: String
    let latitude: String

    var coordinate : CLLocationCoordinate2D {
        return CLLocationCoordinate2D(latitude: Double(latitude) ?? 0.0, longitude: Double(longitude) ?? 0.0)
    }
}