带有嵌套数据的 Swift 4 JSON 解码器

Posted

技术标签:

【中文标题】带有嵌套数据的 Swift 4 JSON 解码器【英文标题】:Swift 4 JSON decoder with nested data 【发布时间】:2018-10-18 14:17:26 【问题描述】:

这是数据结构(更新):

    
  "date": "2018-10-18",
  "time_of_day": "16:00",
  "request_time": "2018-10-18T16:00:27+01:00",
  "station_name": "London Waterloo",
  "station_code": "WAT",
  "arrivals": 
    "all": [
      
        "mode": "train",
        "service": "24673605",
        "train_uid": "W12378",
        "platform": "10",
        "operator": "SW",
        "operator_name": "South Western Railway",
        "aimed_departure_time": null,
        "aimed_arrival_time": "05:18",
        "aimed_pass_time": null,
        "origin_name": "Guildford",
        "destination_name": "London Waterloo",
        "source": "ATOC",
        "category": "OO",
        "service_timetable": 
          "id": "https://transportapi.com/v3/uk/train/service/train_uid:W12378/2018-10-18/timetable.json?app_id=80b56d0a&app_key=b44a5870830959a7a961fdbb65f9dc13"
        
      ,
      
        "mode": "train",
        "service": "24671505",
        "train_uid": "W14110",
        "platform": "1",
        "operator": "SW",
        "operator_name": "South Western Railway",
        "aimed_departure_time": null,
        "aimed_arrival_time": "05:35",
        "aimed_pass_time": null,
        "origin_name": "Twickenham",
        "destination_name": "London Waterloo",
        "source": "ATOC",
        "category": "OO",
        "service_timetable": 
          "id": "https://transportapi.com/v3/uk/train/service/train_uid:W14110/2018-10-18/timetable.json?app_id=80b56d0a&app_key=b44a5870830959a7a961fdbb65f9dc13"
        
      ,
      
        "mode": "train",
        "service": "24671105",
        "train_uid": "W14764",
        "platform": "15",
        "operator": "SW",
        "operator_name": "South Western Railway",
        "aimed_departure_time": null,
        "aimed_arrival_time": "05:41",
        "aimed_pass_time": null,
        "origin_name": "Staines",
        "destination_name": "London Waterloo",
        "source": "ATOC",
        "category": "OO",
        "service_timetable": 
          "id": "https://transportapi.com/v3/uk/train/service/train_uid:W14764/2018-10-18/timetable.json?app_id=80b56d0a&app_key=b44a5870830959a7a961fdbb65f9dc13"
        
      
    ]
  

我在这里尝试过答案:Expected to decode Array<Any> but found a dictionary instead

但不能完全让它工作。我一直在这条线上出错:

let root = try JSONDecoder().decode(Root.self, from: data)

我的模型(更新):

 struct Root: Decodable 
    let arrivals: Arrivals


struct Arrivals: Decodable 
    let all: All


struct All: Decodable 
    let trains: [Train]

错误:

▿ DecodingError
  ▿ typeMismatch : 2 elements
    - .0 : Swift.Dictionary<Swift.String, Any>
    ▿ .1 : Context
      ▿ codingPath : 2 elements
        - 0 : CodingKeys(stringValue: "arrivals", intValue: nil)
        - 1 : CodingKeys(stringValue: "all", intValue: nil)
      - debugDescription : "Expected to decode Dictionary<String, Any> but found an array instead."
      - underlyingError : nil

【问题讨论】:

departures 在您的 struct 中等效键在哪里?应该是Root的key。 @matt 我没有展示真正的 JSON,因为它很长。我只是截断了结尾 啊,错误的样本@larme!道歉。将更新为正确的。 @matt,是的,对不起,伙计,拿错样本了。 【参考方案1】:

“我在这里尝试过答案:Expected to decode Array but found a dictionary instead

是的,但您的错误信息正好相反。花点时间阅读错误信息,我们可以看到它非常清楚,显然是正确的。

在您的 Arrivals 结构中,您说的是

let all: All

但是 JSON 中 "all" 键的值是一个数组!所以这里的类型一定是一个数组。特别是它应该是一系列火车。

let all: [Train]

现在你可以删除你的 All 结构,这从来都不是正确的。

示例(针对您展示的 JSON 运行):

struct Root: Decodable 
    let arrivals: Arrivals

struct Arrivals: Decodable 
    let all: [Train]

struct Train: Decodable 

let data = json.data(using: .utf8)!
if let root = try? JSONDecoder().decode(Root.self, from: data) 
    print("got", String(root.arrivals.all.count), "trains")

// "got 3 trains"

【讨论】:

是的,我也试过了。但这不是错误所指的。让我更新最新的值。错误是说arrivalsnil 不过,我的回答完全符合你提出的问题。 我的回答对我来说似乎仍然正确。删除你的 All 结构并按照我说的做。 对不起@matt,但事实并非如此,解析器甚至没有走那么远。看看上面的错误格式更好。 这就是我所说的。它解码到达,但不能全部解码。你没有按照我说的去做,这当然是行不通的。

以上是关于带有嵌套数据的 Swift 4 JSON 解码器的主要内容,如果未能解决你的问题,请参考以下文章

使用可选值 Swift 4 解码嵌套 JSON

如何在 swift 4.1 和 xcode 9.3 中使用 JSONDecoder 解码嵌套的 JSON 数组和对象?

如何在 swift 4 中使用 JSONDecoder 从嵌套 JSON 中获取数据?

当您不知道 Swift 中的项目类型时,如何解码嵌套的 JSON 数据? [复制]

带有可配置键的 Swift 4 JSON 解码

Swift 使用Codable协议进行json转模型