使用 Codable 解析嵌套 JSON 数据问题

Posted

技术标签:

【中文标题】使用 Codable 解析嵌套 JSON 数据问题【英文标题】:Using Codable to parse nested JSON data problem 【发布时间】:2018-12-15 07:48:07 【问题描述】:

*我正在尝试使用 Codable 来解析复杂的 JSON 数据。但我对"route_polyline"field 有疑问。

问题:

CodingKeys(stringValue: "route_polyline", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "预期解码 Dictionary 但找到了一个数组。

有什么帮助吗?我想使用 Codable 而不是 JSONSerialization。

我的模特:

struct RouteFareResponse: Decodable 
    let status: String
    let trip_cost: Trip_cost

struct Trip_cost: Decodable 

    let start_address: String
    let end_address: String
    let trip_time: Int
    let trip_distance: String

    let transmit_cost: Int
    let cost_in_zone: Int
    let outdoor_zone_cost: Int
    let sub_zones_cost: Int

    let perform_cost: Int
    let services_cost: Int
    let min_cost: Int
    let discount_by_promo: Int
    let result_trip_cost:Int
    let trip_cost: Int
    let trip_cost_with_discount: Int
    let route_polyline: [Polyline]

    let _debug_sub_zones_info: String//Dict
    let _debug: [Debug]




struct Polyline: Decodable 
    var lat: Double
    var long: Double

    enum PolylineKeys: String, CodingKey 
        case route_polyline
    

    init(from decoder: Decoder) throws 
        let values = try decoder.container(keyedBy: PolylineKeys.self)
        var route_polyline = try values.nestedUnkeyedContainer(forKey: .route_polyline)
        var longLat = try route_polyline.nestedUnkeyedContainer()
        long = try longLat.decode(Double.self)
        lat = try longLat.decode(Double.self)
    



struct Debug: Codable 
    let trip_distance: Int
    let trip_time: Int
    let zone_distance: Int
    let zone_time: Int
    let out_zone_distance: Int
    let out_zone_time: Int
//    let transmit_distance: NSNull
//    let transmit_time: NSNull
    let tariff_price_prefix: String

JSON 响应:


    "status": "success",
    "trip_cost": 
        "start_address": "2-й Павловский пер., 18, Москва, Россия, 115093",
        "end_address": "Piața Marii Adunări Naționale, Bulevardul Ștefan cel Mare și Sfînt, Chișinău, Молдавия",
        "trip_time": 934,
        "trip_distance": "1,314.52",
        "transmit_cost": 0,
        "cost_in_zone": 0,
        "outdoor_zone_cost": 0,
        "sub_zones_cost": 0,
        "perform_cost": 0,
        "services_cost": 0,
        "min_cost": 0,
        "discount_by_promo": 0,
        "result_trip_cost": 0,
        "trip_cost": 0,
        "trip_cost_with_discount": 0,
        "route_polyline": [
            [
                55.71801,
                37.62929
            ],
            [
                55.71376,
                37.63317
            ],
            [
                55.71108,
                37.62459
            ],
            [
                55.70636,
                37.62239
            ],
            [
                55.70134,
                37.608
            ],
            [
                55.7115,
                37.58071
            ],
            [
                55.67312,
                37.52316
            ],
            [
                55.63334,
                37.44638
            ],
            [
                55.54088,
                37.08855
            ],
            [
                55.51861,
                36.99843
            ],
            [
                55.47076,
                36.92839
            ],
            [
                55.36682,
                36.75983
            ],
            [
                55.33846,
                36.72214
            ],
            [
                55.32199,
                36.70649
            ],
            [
                55.2975,
                36.70001
            ],
            [
                55.2369,
                36.68447
            ],
            [
                55.17533,
                36.67373
            ],
            [
                55.07732,
                36.62831
            ],
            [
                55.04849,
                36.60693
            ],
            [
                55.0127,
                36.54831
            ],
            [
                54.97539,
                36.48667
            ],
            [
                54.92141,
                36.39975
            ],
            [
                54.90194,
                36.36941
            ],
            [
                54.8747,
                36.35157
            ],
            [
                54.83675,
                36.32096
            ],
            [
                54.77415,
                36.23814
            ],
            [
                54.73767,
                36.18605
            ],
            [
                54.71318,
                36.16446
            ],
            [
                54.64494,
                36.13463
            ],
            [
                54.62446,
                36.12338
            ],
            [
                54.59645,
                36.08795
            ],
            [
                54.54708,
                36.01808
            ],
            [
                54.5191,
                35.97127
            ],
            [
                54.47491,
                35.88614
            ],
            [
                54.40394,
                35.73519
            ],
            [
                54.36474,
                35.62843
            ],
            [
                54.32196,
                35.50525
            ],
            [
                54.24807,
                35.43855
            ],
            [
                54.18797,
                35.34998
            ],
            [
                54.15873,
                35.29848
            ],
            [
                54.14077,
                35.28455
            ],
            [
                54.09443,
                35.2272
            ],
            [
                54.04353,
                35.14278
            ],
            [
                53.99988,
                35.08885
            ],
            [
                53.95291,
                35.02331
            ],
            [
                53.89699,
                34.94324
            ],
            [
                53.78786,
                34.82704
            ],
            [
                53.76976,
                34.81073
            ],
            [
                53.74931,
                34.80781
            ],
            [
                53.71795,
                34.80157
            ],
            [
                53.66801,
                34.77262
            ],
            [
                53.60077,
                34.7352
            ],
            [
                53.55531,
                34.70988
            ],
            [
                53.4788,
                34.67168
            ],
            [
                53.45724,
                34.66608
            ],
            [
                53.4438,
                34.67235
            ],
            [
                53.41763,
                34.66852
            ],
            [
                53.38279,
                34.65954
            ],
            [
                53.3233,
                34.64507
            ],
            [
                53.21967,
                34.61469
            ],
            [
                53.01306,
                34.5253
            ],
            [
                52.94232,
                34.5251
            ],
            [
                52.84383,
                34.52932
            ],
            [
                52.79696,
                34.53675
            ],
            [
                52.7599,
                34.5311
            ],
            [
                52.71971,
                34.53223
            ],
            [
                52.66035,
                34.53044
            ],
            [
                52.64336,
                34.51429
            ],
            [
                52.6047,
                34.51525
            ],
            [
                52.43118,
                34.50557
            ],
            [
                52.38021,
                34.50342
            ],
            [
                52.35699,
                34.49416
            ],
            [
                52.2817,
                34.46901
            ],
            [
                52.2076,
                34.45348
            ],
            [
                52.17831,
                34.45381
            ],
            [
                52.13737,
                34.47217
            ],
            [
                52.03141,
                34.47033
            ],
            [
                51.93017,
                34.49023
            ],
            [
                51.91541,
                34.44451
            ],
            [
                51.89897,
                34.38614
            ],
            [
                51.86806,
                34.30569
            ],
            [
                51.82,
                34.15201
            ],
            [
                51.78168,
                34.02024
            ],
            [
                51.73943,
                33.92501
            ],
            [
                51.70179,
                33.83608
            ],
            [
                51.65752,
                33.70137
            ],
            [
                51.54035,
                33.4268
            ],
            [
                51.52512,
                33.38398
            ],
            [
                51.4958,
                33.3356
            ],
            [
                51.44937,
                33.23951
            ],
            [
                51.42716,
                33.16679
            ],
            [
                51.40182,
                33.06367
            ],
            [
                51.3634,
                32.98993
            ],
            [
                51.34672,
                32.91794
            ],
            [
                51.32141,
                32.87128
            ],
            [
                51.2664,
                32.6516
            ],
            [
                51.23106,
                32.48914
            ],
            [
                51.20507,
                32.29943
            ],
            [
                51.16934,
                32.07204
            ],
            [
                51.1508,
                31.97069
            ],
            [
                51.13949,
                31.8706
            ],
            [
                51.13728,
                31.70108
            ],
            [
                51.13263,
                31.62517
            ],
            [
                51.1191,
                31.52805
            ],
            [
                51.08803,
                31.30808
            ],
            [
                51.06756,
                31.15402
            ],
            [
                50.99689,
                31.13589
            ],
            [
                50.95574,
                31.12393
            ],
            [
                50.93721,
                31.1177
            ],
            [
                50.92171,
                31.09714
            ],
            [
                50.90721,
                31.08228
            ],
            [
                50.8909,
                31.07671
            ],
            [
                50.84758,
                31.043
            ],
            [
                50.7346,
                30.95449
            ],
            [
                50.52917,
                30.79495
            ],
            [
                50.4994,
                30.77167
            ],
            [
                50.48368,
                30.71295
            ],
            [
                50.46354,
                30.63963
            ],
            [
                50.46132,
                30.6289
            ],
            [
                50.45511,
                30.63293
            ],
            [
                50.43845,
                30.6127
            ],
            [
                50.42376,
                30.5699
            ],
            [
                50.42164,
                30.55162
            ],
            [
                50.40604,
                30.51815
            ],
            [
                50.39558,
                30.50879
            ],
            [
                50.38195,
                30.47954
            ],
            [
                50.32586,
                30.39378
            ],
            [
                50.29453,
                30.35951
            ],
            [
                50.26486,
                30.33643
            ],
            [
                50.25778,
                30.31004
            ],
            [
                50.24634,
                30.28063
            ],
            [
                50.22903,
                30.26774
            ],
            [
                50.18994,
                30.2224
            ],
            [
                50.18091,
                30.21798
            ],
            [
                50.16218,
                30.2255
            ],
            [
                50.14369,
                30.23776
            ],
            [
                50.13303,
                30.23166
            ],
            [
                50.11478,
                30.23418
            ],
            [
                50.08751,
                30.23467
            ],
            [
                50.05339,
                30.21647
            ],
            [
                50.03091,
                30.21478
            ],
            [
                50.00816,
                30.2016
            ],
            [
                49.95806,
                30.17323
            ],
            [
                49.9348,
                30.18623
            ],
            [
                49.92008,
                30.19057
            ],
            [
                49.89046,
                30.17741
            ],
            [
                49.83993,
                30.15933
            ],
            [
                49.80218,
                30.19935
            ],
            [
                49.75538,
                30.19921
            ],
            [
                49.69172,
                30.19481
            ],
            [
                49.56323,
                30.17288
            ],
            [
                49.50329,
                30.16781
            ],
            [
                49.459,
                30.15574
            ],
            [
                49.41405,
                30.12468
            ],
            [
                49.37424,
                30.11152
            ],
            [
                49.33214,
                30.10614
            ],
            [
                49.23068,
                30.08139
            ],
            [
                49.20557,
                30.07636
            ],
            [
                49.17632,
                30.08126
            ],
            [
                49.14088,
                30.08948
            ],
            [
                49.13227,
                30.10026
            ],
            [
                49.12034,
                30.14063
            ],
            [
                49.11067,
                30.14782
            ],
            [
                49.05454,
                30.15435
            ],
            [
                49.01042,
                30.16103
            ],
            [
                48.98754,
                30.16486
            ],
            [
                48.97725,
                30.17264
            ],
            [
                48.92938,
                30.23371
            ],
            [
                48.91232,
                30.24705
            ],
            [
                48.8892,
                30.25526
            ],
            [
                48.86788,
                30.25988
            ],
            [
                48.8302,
                30.25662
            ],
            [
                48.77143,
                30.25854
            ],
            [
                48.72721,
                30.25507
            ],
            [
                48.6695,
                30.23987
            ],
            [
                48.56247,
                30.23094
            ],
            [
                48.50009,
                30.22887
            ],
            [
                48.41243,
                30.24079
            ],
            [
                48.213,
                30.28787
            ],
            [
                48.15789,
                30.3029
            ],
            [
                48.13357,
                30.30171
            ],
            [
                48.05351,
                30.29445
            ],
            [
                47.96978,
                30.30973
            ],
            [
                47.91599,
                30.31322
            ],
            [
                47.85884,
                30.30052
            ],
            [
                47.8276,
                30.29059
            ],
            [
                47.79247,
                30.2623
            ],
            [
                47.75315,
                30.27486
            ],
            [
                47.7404,
                30.27392
            ],
            [
                47.72084,
                30.21455
            ],
            [
                47.70569,
                30.12985
            ],
            [
                47.69383,
                30.0688
            ],
            [
                47.67141,
                29.99311
            ],
            [
                47.65685,
                29.89882
            ],
            [
                47.63792,
                29.83431
            ],
            [
                47.62534,
                29.80075
            ],
            [
                47.62718,
                29.74939
            ],
            [
                47.63537,
                29.68184
            ],
            [
                47.58942,
                29.57482
            ],
            [
                47.55006,
                29.5017
            ],
            [
                47.49814,
                29.45195
            ],
            [
                47.45969,
                29.41467
            ],
            [
                47.4303,
                29.37051
            ],
            [
                47.33885,
                29.24453
            ],
            [
                47.32377,
                29.22576
            ],
            [
                47.30789,
                29.20682
            ],
            [
                47.27122,
                29.20243
            ],
            [
                47.25495,
                29.19737
            ],
            [
                47.2455,
                29.18709
            ],
            [
                47.23985,
                29.17093
            ],
            [
                47.22769,
                29.13168
            ],
            [
                47.1724,
                29.01439
            ],
            [
                47.12864,
                28.91717
            ],
            [
                47.11337,
                28.86019
            ],
            [
                47.10136,
                28.86359
            ],
            [
                47.0479,
                28.84916
            ],
            [
                47.03916,
                28.85336
            ],
            [
                47.02463,
                28.83238
            ]
        ],
        "_debug_sub_zones_info": ,
        "_debug": 
            "trip_distance": 1314516,
            "trip_time": 56015,
            "zone_distance": 10385.483746984,
            "zone_time": 560,
            "out_zone_distance": 1297603.4600007,
            "out_zone_time": 55455,
            "transmit_distance": null,
            "transmit_time": null,
            "tariff_price_prefix": "night_"
        
    

发现有点相同的问题,但解决方案 in this topic 仅适用于前几个坐标

【问题讨论】:

【参考方案1】:

route_polyline的值是一个嵌套数组,但是你必须将内部数组直接解码为lat/long。 将Polyline 结构更改为

struct Polyline: Decodable 
    let lat: Double
    let long: Double

    init(from decoder: Decoder) throws 
        var longLat = try decoder.unkeyedContainer()
        long = try longLat.decode(Double.self)
        lat = try longLat.decode(Double.self)
    

请避免 snake_cased 变量。您可以使用 .convertFromSnakeCase 键解码策略将这些键解码为 lowerCamelCased 变量。

【讨论】:

以上是关于使用 Codable 解析嵌套 JSON 数据问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Codable 和 Swift 解析这个嵌套的 JSON?

iOS swift Codable 不能与 Alamofire 一起使用 JSON 嵌套数据?

使用 URLSession 和 Codable 解析 JSON 数据

JSON 解析,嵌套 JSON 结构的问题

使用 Codable 解析 JSON 数据

使用 Codable 解析多级 JSON