簡體   English   中英

使用Codable解析嵌套的JSON數據

[英]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)

    }
}

JSON響應

{  
   "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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM