【发布时间】:2017-12-27 08:28:05
【问题描述】:
来自 API 的格式非常糟糕的 json 响应:
[{
"id": "1",
"shape": "{
"coordinates": "[[12.557642081093963,99.95730806607756], [12.558081912207575,99.96078957337888], [12.558469381851197,99.96072520036252], [12.558029551400157,99.9572275998071]]"}"
}]
我需要将这个“形状”键解码到我的自定义结构中,这似乎没什么大不了,但我有引号包裹数组 "[]"
所以,我有什么:
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Identifier.self, forKey: .id)
shape = try container
.nestedContainer(keyedBy: ShapeCoordinatesCodingKeys.self, forKey: .shape)
.decode([[Double]].self, forKey: .coordinates)
.flatMap {
$0.count > 1 ? Location(latitude: $0[0], longitude: $0[1]) : nil
}
}
合理有错误
"Expected to decode Array<Any> but found a string/data instead."
而且这个调用确实有效(仅用于测试目的):
po try container.nestedContainer(keyedBy: ShapeCoordinatesCodingKeys.self, forKey: .shape).decode(String.self, forKey: .coordinates)
并有这个输出:
"[[12.557642081093963,99.95730806607756], [12.558081912207575,99.96078957337888], [12.558469381851197,99.96072520036252], [12.558029551400157,99.9572275998071]]"
所以有什么方法可以使用Codable 将此字符串样式包装的 json 数组解码为 Swift 数组?
我设法做了一些解决方法,它有效,但它似乎根本不是一个好的解决方案。将在此处发布,但“是否有任何方法可以正常使用 Codable 实现此功能”的问题仍然存在
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Identifier.self, forKey: .id)
do {
shape = try container
.nestedContainer(keyedBy: ShapeCoordinatesCodingKeys.self, forKey: .shape)
.decode([[Double]].self, forKey: .coordinates)
.flatMap {
$0.count > 1 ? Location(latitude: $0[0], longitude: $0[1]) : nil
}
}
catch {
guard let coordinatesData = try container
.nestedContainer(keyedBy: ShapeCoordinatesCodingKeys.self, forKey: .shape)
.decode(String.self, forKey: .coordinates).data(using: .utf8) else {
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: [ShapeCoordinatesCodingKeys.coordinates],
debugDescription: "Array or String?"
)
)
}
shape = try JSONDecoder()
.decode([[Double]].self, from: coordinatesData)
.flatMap {
$0.count > 1 ? Location(latitude: $0[0], longitude: $0[1]) : nil
}
}
}
【问题讨论】:
-
因为
coordinates的值似乎是纯String而不是Array,您需要将该特定的String值转换为JSON(如果它应该是一个有效的 JSON)并单独对其进行解码。 -
@holex 这个是合法的json,但是因为被当作String处理所以不能正常解码,这里不能怪JSONDecoder,这都可以理解
-
这似乎是故意发送为
String而不是Array(出于某种原因),这纯粹是后端的情况,即使该字符串当前格式为一个有效的 JSON,从解析器的角度来看,它仍然是一个原始字符串,并且它可以在任何时候进行任何其他操作 - 显然JSONEcoder无法将其解析为原始字符串的值,而不是可解码的结构。
标签: json swift swift4 codable decodable