我正在尝试使用Swift Struct的Encodable协议解析以下json。
如果我将坐标设为Any
或AnyObject
,则会出现错误,提示您不符合协议。
我知道可以使用数组和字典来实现,但是我不想那样做。
{
"coordinates": [
[
[
0.148271,
51.6723432
],
[
0.148271,
51.3849401
],
[
-0.3514683,
51.3849401
],
[
-0.3514683,
51.6723432
],
[
0.148271,
51.6723432
]
]
]
}
struct Geometry: Codable {
let coordinates: [[[Double]]]
init(from decoder: Decoder) throws {
let data = try decoder.container(keyedBy: CodingKeys.self)
coordinates = try data.decode([[[Double]]].self, forKey: .coordinates)
}
}
do {
let decoded = try JSONDecoder().decode(Geometry.self, from: data!)
print(decoded)
completionHandler(statusCode, decoded)
} catch {
print("Failed to encode data.")
completionHandler(statusCode, nil)
}
如何解决此问题?
答案 0 :(得分:1)
我的建议是使CLLocationCoordinate2D
符合Codable
解码Double
的数组
import CoreLocation
extension CLLocationCoordinate2D : Codable {
public init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
if arrayContainer.count == 2 {
let lat = try arrayContainer.decode(CLLocationDegrees.self)
let lng = try arrayContainer.decode(CLLocationDegrees.self)
self.init(latitude: lat, longitude: lng)
} else {
throw DecodingError.dataCorruptedError(in: arrayContainer, debugDescription: "Coordinate array must contain two items")
}
}
public func encode(to encoder: Encoder) throws {
var arrayContainer = encoder.unkeyedContainer()
try arrayContainer.encode(contentsOf: [latitude, longitude])
}
}
然后您可以简单地声明Geometry
struct Geometry: Codable {
let coordinates: [[CLLocationCoordinate2D]]
}
答案 1 :(得分:-1)
您在原始问题中呈现的数据段(在阅读我的评论后多次编辑之前)不是有效的JSON。 如果在所有内容(现在都拥有)周围加上大括号,则它将是带有“ coordinates”字段的有效JSON对象。但是从您的(原始)问题中我知道那可能不是您想要的。可以得到的第二个最好的东西是有效的JSON是Array(即“ coordinates”字段的内容。)
以下代码段提供了JSON对象:
import Foundation
let sample = [[[0.148271, 51.6723432], [0.148272, 51.6723433], [0.148273, 51.6723434],]]
struct Geometry: Codable {
var coordinates: [[[Double]]]
init(coord: [[[Double]]]) {
self.coordinates = coord
}
//// Remove the comments below in order use a simple JSON array!
// func encode(to encoder: Encoder) throws {
// var container = encoder.singleValueContainer()
// try container.encode(coordinates)
// }
//
// init(from decoder: Decoder) throws {
// let container = try decoder.singleValueContainer()
// coordinates = try container.decode([[[Double]]].self)
// }
}
// Initialize a Geometry object
let geo = Geometry(coord: sample)
// Serialize into `data` and print the result
let data = try! JSONEncoder().encode(geo)
print (String(data: data, encoding: .utf8) ?? "-not representable-")
// Now, decode the data into a new Geometry instance `g` and print it
let g = try! JSONDecoder().decode(Geometry.self, from: data)
print (g)
这导致(JSON格式具有更好的可读性):
{
"coordinates": [
[
[
0.14827099999999999,
51.6723432
],
[
0.14827199999999999,
51.672343300000001
],
[
0.14827299999999999,
51.672343400000003
]
]
]
}
Geometry(coordinates: [[[0.148271, 51.6723432], [0.148272, 51.6723433], [0.148273, 51.6723434]]])
如果删除示例代码中的注释,则得到的数组不带花括号,但不带“ coordinates”:标签(JSON格式具有更好的可读性):
[
[
[
0.14827099999999999,
51.6723432
],
[
0.14827199999999999,
51.672343300000001
],
[
0.14827299999999999,
51.672343400000003
]
]
]
Geometry(coordinates: [[[0.148271, 51.6723432], [0.148272, 51.6723433], [0.148273, 51.6723434]]])