У меня есть этот JSON-файл.
[
{
"name": "January",
"holidays": [
{
"name": "New Year's Day",
"date": "2019-01-01T00:00:00-0500",
"type": {
"isNationalHoliday": true,
"isRegionalHoliday": true,
"isPublicHoliday": true,
"isGovernmentHoliday": true
}
},
{
"name": "Martin Luther King Day",
"date": "2019-01-21T00:00:00-0500",
"type": {
"isNationalHoliday": true,
"isRegionalHoliday": true,
"isPublicHoliday": true,
"isGovernmentHoliday": true
}
}
]
},
{
"name": "February",
"holidays": [
{
"name": "Presidents' Day",
"date": "2019-02-18T00:00:00-0500",
"type": {
"isNationalHoliday": false,
"isRegionalHoliday": true,
"isPublicHoliday": false,
"isGovernmentHoliday": false
}
}
]
},
{
"name": "March",
"holidays": null
}
]
Я создал структуру Month
для декодирования словарей в JSON.
public struct Month {
public let name: String
public let holidays: [Holiday]?
}
extension Month: Decodable { }
И структуру Year
для храненияих все.
public struct Year {
public let months: [Month]
}
extension Year: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let values = try container.decode([Month].self)
months = values
}
}
Моя структура Holiday
немного сложнее из-за наличия перечисления с именем HolidayType
, где я хочу декодировать значения в поле type
в JSON.
public struct Holiday {
public let name: String
public let date: Date
public let type: HolidayType
}
extension Holiday: Decodable { }
public enum HolidayType {
case isNationalHoliday
case isRegionalHoliday
case isPublicHoliday
case isGovernmentHoliday
enum CodingKeys: String, CodingKey {
case isNationalHoliday
case isRegionalHoliday
case isPublicHoliday
case isGovernmentHoliday
}
}
extension HolidayType: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self = try container.decode(HolidayType.self, forKey: .isNationalHoliday)
self = try container.decode(HolidayType.self, forKey: .isRegionalHoliday)
self = try container.decode(HolidayType.self, forKey: .isPublicHoliday)
self = try container.decode(HolidayType.self, forKey: .isGovernmentHoliday)
}
}
Здесь я загружаю файл и декодирую.
if let url = Bundle.main.url(forResource: "holidays", withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let year = try decoder.decode(Year.self, from: data)
print(year.months)
} catch let error {
print("Error occurred decoding JSON: \(error)")
}
} else {
print("Error occurred loading file")
}
Но происходит сбой со следующей ошибкой.
typeMismatch (Swift.Dictionary, Swift.DecodingError.Context (codingPath: [_JSONKey (stringValue: "Index 0", intValue: 0), CodingKeys (stringValue: "праздничные дни", intValue: nil), _JSONKey (stringValue: stringValue: "Index 0", intValue: 0), CodingKeys (stringValue: "type", intValue: nil), CodingKeys (stringValue: "isNationalHoliday", intValue: nil)], debugDescription: "Ожидается декодировать словарь, но вместо этого найдено число.", BasedError: nil))
Я не могу понять, как это исправить.Я также загрузил демонстрационный проект здесь .