Codable 错误 - 预期解码字典 <String, Any> 但找到数组
Codable Error - Expected to decode Dictionary <String, Any> but found array
请有人帮我指出哪里做错了。我已经搜索过其他类似的问题,但没有一个似乎有助于解决这个问题
我正在尝试使用 Swift Codable
解码 json
我已经创建了嵌套的可编码结构,但它总是失败。
我正在尝试解码的 json 可以在这里找到 - https://pastebin.com/C0QCREEF
这是失败的可编码结构 -
struct OutboundFlightData: Codable {
var data: OutboundFlight
}
struct OutboundFlight: Codable {
var outboundFlights: [OutboundFlightDetails]
}
struct OutboundFlightDetails: Codable {
var amount: String
var fareFamily: Bool
var cabin: String
var fareBasis: String
var duration: String
var itinerary: [OutboundFlightItinerary]
}
struct OutboundFlightItinerary: Codable {
var timeOfDeparture: String
var timeOfArrival: String
var dateOfDeparture: String
var dateOfArrival: String
var departureLocation: String
var departureDetails: FlightItineraryDetails
var arrivalLocation: String
var arrivalDetails: [FlightItineraryDetails]
var departureTerminal: String?
var arrivalTerminal: String?
var operatingCompany: String
var operatingDetails: FlightItineraryOperatingDetails
var marketingCompany: String
var marketingDetails: FlightItineraryOperatingDetails
var flightNumber: String
var electronicTicketing: String
}
struct FlightItineraryOperatingDetails: Codable {
var iata: String
var fullName: String
var countryName: String
var logoSmall: String
var logo: String
enum CodingKeys: String, CodingKey {
case iata
case fullName = "full_name"
case logoSmall = "logo_small"
case logo
case countryName = "country_name"
}
}
struct FlightItineraryDetails: Codable {
var iata: String
var name: String
var cityName: String
var stateName: String
var countryName: String
enum CodingKeys: String, CodingKey {
case iata
case name
case cityName = "city_name"
case stateName = "state_name"
case countryName = "country_name"
}
}
我希望 json 能够成功解码。但是我一直收到错误 -
typeMismatch(
Swift.Array<Any>,
Swift.DecodingError.Context(
codingPath: [
CodingKeys(stringValue: "data", intValue: nil),
CodingKeys(stringValue: "outboundFlights", intValue: nil),
_JSONKey(stringValue: "Index 0", intValue: 0),
CodingKeys(stringValue: "itinerary", intValue: nil),
_JSONKey(stringValue: "Index 0", intValue: 0),
CodingKeys(stringValue: "arrivalDetails", intValue: nil)
],
debugDescription: "Expected to decode Array<Any> but found a dictionary instead.",
underlyingError: nil
)
)
但是当我从数组中更改 arrivalDetails 时。我得到这个错误
typeMismatch(
Swift.Dictionary<Swift.String, Any>,
Swift.DecodingError.Context(
codingPath: [
CodingKeys(stringValue: "data", intValue: nil),
CodingKeys(stringValue: "outboundFlights", intValue: nil),
_JSONKey(stringValue: "Index 6", intValue: 6),
CodingKeys(stringValue: "itinerary", intValue: nil),
_JSONKey(stringValue: "Index 1", intValue: 1),
CodingKeys(stringValue: "arrivalDetails", intValue: nil)
],
debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.",
underlyingError: nil
)
)
从您提供的示例 JSON 看来,arrivalDetails 字段是用字典或空数组填充的。这就是为什么当您在 [FlightItineraryDetails]
和 FlightItineraryDetails
之间切换时,无论哪种方式都会出错,因为解码器无法将字典解析为数组,或将数组解析为字典。
不幸的是,Codable 无法立即处理这种情况。您需要为这种情况创建一个枚举,尝试以两种方式解析该键,返回它在数据中找到的任何一个。
(此代码无耻地从将 JSON 馈送到 https://app.quicktype.io 的输出中提取出来。我总是建议使用它来将 JSON 个示例从 API 映射到可编码结构。它至少让你完成了 80% 的事情,并处理了像这样 API 表现不佳的奇怪情况。)
enum ArrivalDetails: Codable {
case anythingArray([JSONAny])
case details(Details)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode([JSONAny].self) {
self = .anythingArray(x)
return
}
if let x = try? container.decode(Details.self) {
self = .details(x)
return
}
throw DecodingError.typeMismatch(ArrivalDetails.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ArrivalDetails"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .anythingArray(let x):
try container.encode(x)
case .details(let x):
try container.encode(x)
}
}
}
如果您可以控制 returns 这个结果的 API,您可以考虑将该字段更改为不存在,或者如果该字段应为空则设置为 null,而不是一个空数组。然后你可以简单地把它改回 [FlightItineraryDetails]?
.
请有人帮我指出哪里做错了。我已经搜索过其他类似的问题,但没有一个似乎有助于解决这个问题 我正在尝试使用 Swift Codable
解码 json我已经创建了嵌套的可编码结构,但它总是失败。
我正在尝试解码的 json 可以在这里找到 - https://pastebin.com/C0QCREEF
这是失败的可编码结构 -
struct OutboundFlightData: Codable {
var data: OutboundFlight
}
struct OutboundFlight: Codable {
var outboundFlights: [OutboundFlightDetails]
}
struct OutboundFlightDetails: Codable {
var amount: String
var fareFamily: Bool
var cabin: String
var fareBasis: String
var duration: String
var itinerary: [OutboundFlightItinerary]
}
struct OutboundFlightItinerary: Codable {
var timeOfDeparture: String
var timeOfArrival: String
var dateOfDeparture: String
var dateOfArrival: String
var departureLocation: String
var departureDetails: FlightItineraryDetails
var arrivalLocation: String
var arrivalDetails: [FlightItineraryDetails]
var departureTerminal: String?
var arrivalTerminal: String?
var operatingCompany: String
var operatingDetails: FlightItineraryOperatingDetails
var marketingCompany: String
var marketingDetails: FlightItineraryOperatingDetails
var flightNumber: String
var electronicTicketing: String
}
struct FlightItineraryOperatingDetails: Codable {
var iata: String
var fullName: String
var countryName: String
var logoSmall: String
var logo: String
enum CodingKeys: String, CodingKey {
case iata
case fullName = "full_name"
case logoSmall = "logo_small"
case logo
case countryName = "country_name"
}
}
struct FlightItineraryDetails: Codable {
var iata: String
var name: String
var cityName: String
var stateName: String
var countryName: String
enum CodingKeys: String, CodingKey {
case iata
case name
case cityName = "city_name"
case stateName = "state_name"
case countryName = "country_name"
}
}
我希望 json 能够成功解码。但是我一直收到错误 -
typeMismatch(
Swift.Array<Any>,
Swift.DecodingError.Context(
codingPath: [
CodingKeys(stringValue: "data", intValue: nil),
CodingKeys(stringValue: "outboundFlights", intValue: nil),
_JSONKey(stringValue: "Index 0", intValue: 0),
CodingKeys(stringValue: "itinerary", intValue: nil),
_JSONKey(stringValue: "Index 0", intValue: 0),
CodingKeys(stringValue: "arrivalDetails", intValue: nil)
],
debugDescription: "Expected to decode Array<Any> but found a dictionary instead.",
underlyingError: nil
)
)
但是当我从数组中更改 arrivalDetails 时。我得到这个错误
typeMismatch(
Swift.Dictionary<Swift.String, Any>,
Swift.DecodingError.Context(
codingPath: [
CodingKeys(stringValue: "data", intValue: nil),
CodingKeys(stringValue: "outboundFlights", intValue: nil),
_JSONKey(stringValue: "Index 6", intValue: 6),
CodingKeys(stringValue: "itinerary", intValue: nil),
_JSONKey(stringValue: "Index 1", intValue: 1),
CodingKeys(stringValue: "arrivalDetails", intValue: nil)
],
debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.",
underlyingError: nil
)
)
从您提供的示例 JSON 看来,arrivalDetails 字段是用字典或空数组填充的。这就是为什么当您在 [FlightItineraryDetails]
和 FlightItineraryDetails
之间切换时,无论哪种方式都会出错,因为解码器无法将字典解析为数组,或将数组解析为字典。
不幸的是,Codable 无法立即处理这种情况。您需要为这种情况创建一个枚举,尝试以两种方式解析该键,返回它在数据中找到的任何一个。
(此代码无耻地从将 JSON 馈送到 https://app.quicktype.io 的输出中提取出来。我总是建议使用它来将 JSON 个示例从 API 映射到可编码结构。它至少让你完成了 80% 的事情,并处理了像这样 API 表现不佳的奇怪情况。)
enum ArrivalDetails: Codable {
case anythingArray([JSONAny])
case details(Details)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode([JSONAny].self) {
self = .anythingArray(x)
return
}
if let x = try? container.decode(Details.self) {
self = .details(x)
return
}
throw DecodingError.typeMismatch(ArrivalDetails.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ArrivalDetails"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .anythingArray(let x):
try container.encode(x)
case .details(let x):
try container.encode(x)
}
}
}
如果您可以控制 returns 这个结果的 API,您可以考虑将该字段更改为不存在,或者如果该字段应为空则设置为 null,而不是一个空数组。然后你可以简单地把它改回 [FlightItineraryDetails]?
.