请有人帮我指出做错了什么。我已经搜索了类似的其他类似问题,但似乎都不能帮助解决此问题 我正在尝试使用Swift Codable解码JSON
我已经创建了嵌套的可编码结构,但是一直失败。
要解码的json可以在这里找到-https://pastebin.com/C0QCREEF
这是失败的可编码结构-
let closed = false;
function* syncGenerator() {
yield* ~20-trillion-calculated-results;
}
function main( generator = syncGenerator() )
{
if (closed)
{
syncGracefulCleanup();
}
else
{
// assuming syncWork returns false when
// there are no more value
if ( syncWork( generator.next() ) )
{
// next-ish off to the event loop. this is NOT recursive,
// even though it may look a bit like it
setTimeout( () => main(generator), 0 );
}
}
}
process.on('SIGINT', () => close = true);
我希望json成功解码。但是我一直收到错误-
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"
}
}
但是当我从array更改到达细节时。我收到此错误
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
)
)
答案 0 :(得分:1)
从您提供的示例JSON来看,到达详细信息字段正在用字典或空数组填充。这就是为什么当您在[FlightItineraryDetails]
和FlightItineraryDetails
之间切换时,由于解码器无法将字典解析为数组或将数组解析为字典而导致错误的原因。
不幸的是,这是Codable无法开箱即用的情况。您需要为这种情况创建一个枚举,尝试以两种方式解析该键,并返回在数据中找到的那个键。
(此代码是从将JSON馈入https://app.quicktype.io的输出中无耻提取的。我总是建议使用该代码将JSON示例从API映射到Codable结构中。它至少使您获得了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)
}
}
}
如果您控制返回此结果的API,则可以考虑将该字段更改为不存在,或者如果该字段应为空而不是空数组,则将其设置为null。然后,您只需将其更改回[FlightItineraryDetails]?
。