[英]Using Codable to parse nested JSON data
我正在嘗試使用Codable
解析JSON數據。 但是當歸結為帶有數組的對象時會遇到一些問題。 我一直在嘗試遵循以下答案 ,但出現錯誤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
]
]
編譯器給您的錯誤是因為您的對象不符合Encodable
如果只需要使用Decodable
> object而不是其他方式,則可以使用Decodable
而不是Codable
。
Codable
要求與Encodable
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)
}
}
首先,如果只想解碼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) }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.