There is two mismatch error . First one because of yearOfBirth variable. Because one of JsonData is String ("") although others are Integer.
Second one is wand variable. Error is:
Expected to decode String but found a dictionary instead
My model is :
struct harryPotter : Codable{
var name : String
var species : String
var gender : String
var house : String
var dateOfBirth : String
var yearOfBirth : Int
var ancestry : String
var eyeColour : String
var hairColour : String
var wand : String
var patronus : String
var hogwartsStudent : Bool
var hogwartsStaff : Bool
var actor : String
var alive : Bool
var image : String
}
struct wand : Codable{
var wood : String
var core : String
var length : Int
}
JSON Data Link : JSON
The error clearly tells that the wand
type should be Wand
instead of String
.
Also, for variables with multiple types, you can use enums.
Also, for options like gender
, you should use enum
instead.
So:
import Foundation
// MARK: - Input
struct Input: Codable {
let name: String
let species: Species
let gender: Gender
let house, dateOfBirth: String
let yearOfBirth: YearOfBirth
let ancestry, eyeColour, hairColour: String
let wand: Wand
let patronus: String
let hogwartsStudent, hogwartsStaff: Bool
let actor: String
let alive: Bool
let image: String
}
enum Gender: String, Codable {
case female = "female"
case male = "male"
}
enum Species: String, Codable {
case cat = "cat"
case halfGiant = "half-giant"
case human = "human"
case werewolf = "werewolf"
}
// MARK: - Wand
struct Wand: Codable {
let wood, core: String
let length: Length
}
enum Length: Codable {
case double(Double)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Double.self) {
self = .double(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Length.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Length"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .double(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
enum YearOfBirth: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(YearOfBirth.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for YearOfBirth"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
typealias Inputs = [Input]