我尝试使用Codable
来解析JSON数据。但是当涉及到具有数组的对象时会遇到一些问题。我一直在尝试关注answer,但我收到了错误Type 'Feature' does not conform to protocol 'Encodable'
我想要的JSON数据是纬度和经度数据,但我很难努力学习Codable
。我还可以补充一点,我试图抓住id
并且它工作正常,但是当我试图更深入时,它只是给了我一个错误。
有什么建议吗?我确实想使用Codable
而不是JSONSerialization
。
struct Features: Codable {
var features: [Feature]
}
struct Feature: Codable {
var lat: Double
var long: Double
enum CodingKeys: String, CodingKey {
case geometry
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let geometry = try values.nestedContainer(keyedBy: CodingKeys.self, forKey: .geometry)
var coordinates = try geometry.nestedUnkeyedContainer(forKey: .geometry)
long = try coordinates.decode(Double.self)
lat = try coordinates.decode(Double.self)
}
}
{
"type":"FeatureCollection",
"totalFeatures":1761,
"features":[
{
"type":"Feature",
"id":"LTFR_P_RORELSEHINDRADE.3179814",
"geometry":{
"type":"LineString",
"coordinates":[
[
17.929374,
59.387507
],
[
17.929364,
59.387493
]
]
},
"geometry_name":"GEOMETRY",
"properties":{
"FID":3179814,
"FEATURE_OBJECT_ID":2406812,
"FEATURE_VERSION_ID":1,
"EXTENT_NO":2,
"VALID_FROM":"2008-10-09T22:00:00Z",
"CITATION":"0180 2008-09122",
"STREET_NAME":"Visbyringen",
"CITY_DISTRICT":"Rinkeby",
"PARKING_DISTRICT":"<Område saknas>",
"ADDRESS":"Visbyringen 4",
"VF_METER":12,
"VF_PLATS_TYP":"Reserverad p-plats rörelsehindrad",
"RDT_URL":"https://rdt.transportstyrelsen.se/rdt/AF06_View.aspx?BeslutsMyndighetKod=0180&BeslutadAr=2008&LopNr=09122"
}
}
]
}
"coordinates":[
[
17.929374,
59.387507
],
[
17.929364,
59.387493
]
]
答案 0 :(得分:2)
编译器给出的错误是因为您的对象不符合Encodable
如果你只需要去JSON - &gt;对象而不是相反,您可以使用Decodable
代替Codable
。
Codable
要求符合Encodable
,因此您还必须实施encode(to encoder: Encoder)
修复之后,您还需要修复嵌套容器的解析。
您的内部几何对象具有与外部对象不同的键,因此您需要单独的CodingKey
才能通过。你还需要比现在更深一层才能达到你的坐标。
此版本适用于您问题中的json:
struct Features: Decodable {
var features: [Feature]
}
struct Feature: Decodable {
var lat: Double
var long: Double
enum CodingKeys: String, CodingKey {
case geometry
}
enum GeometryKeys: String, CodingKey {
case coordinates
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let geometry = try values.nestedContainer(keyedBy: GeometryKeys.self, forKey: .geometry)
var coordinates = try geometry.nestedUnkeyedContainer(forKey: .coordinates)
var longLat = try coordinates.nestedUnkeyedContainer()
long = try longLat.decode(Double.self)
lat = try longLat.decode(Double.self)
}
}
答案 1 :(得分:1)
首先,如果您只想解码JSON,则只采用Decodable
。如果您采用Codable
并编写自定义初始化程序,则还必须编写编码器方法。这是错误的消息。
我建议将JSON解码为单独的结构。这需要更少的代码。写一个CLLocationCoordinate2D
的扩展名作为坐标的包装器,以采用Decodable
import CoreLocation
extension CLLocationCoordinate2D : Decodable {
public init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
let lat = try arrayContainer.decode(CLLocationDegrees.self)
let lng = try arrayContainer.decode(CLLocationDegrees.self)
self.init(latitude: lat, longitude: lng)
}
}
其余只有几行
struct Features: Decodable {
var features: [Feature]
}
struct Feature: Decodable {
let geometry : Geometry
}
struct Geometry: Decodable {
let coordinates : [CLLocationCoordinate2D]
}
你得到
的坐标do {
let result = try JSONDecoder().decode(Features.self, from: data)
for feature in result.features {
print(feature.geometry.coordinates)
}
} catch { print(error) }