Свифт 4 JSON-декодер с вложенными данными

Обновить

March 2019

Просмотры

141 раз

1

Это структура данных (обновление):

    {
  "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"
        }
      }
    ]
  }
}

Я попытался ответить здесь: Ожидаемый декодировать массив <Any> , но нашел словарь вместо

Но не вполне может заставить его работать. Я постоянно получаю и ошибка в этой строке:

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

1 ответы

2

"I've tried the answer here: Expected to decode Array but found a dictionary instead

Yes, but your error message is just the opposite. Taking a moment to read the error message, we can see that it is perfectly clear and obviously right.

In your Arrivals struct, you are saying

let all: All

But the value of the "all" key in the JSON is an array! So the type here must be an array of something. In particular it should be an array of trains.

let all: [Train]

And now you can delete your All struct, which was never right.

Example (running against the JSON you showed):

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"