【问题标题】:Swift JSON Type Mismatch [duplicate]Swift JSON 类型不匹配 [重复]
【发布时间】:2020-12-12 06:51:48
【问题描述】:

有两个不匹配错误。 第一个是因为 yearOfBirth 变量。因为其中一个 JsonData 是 String ("") 而其他的是 Integer。

第二个是wand变量。错误是:应解码字符串,但找到了字典

我的模型是:

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 数据链接: JSON

【问题讨论】:

标签: ios json swift api


【解决方案1】:

错误清楚地表明wand 类型应该是Wand 而不是String

另外,对于具有多种类型的变量,您可以使用枚举。

另外,对于gender 之类的选项,您应该改用enum

所以:

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]

【讨论】:

  • 谢谢。我想再问一个问题。当我将 yearOfBirth 中的数据导出到数组时,如何定义数组?字符串还是整数?会报错
  • 我看不出将类型变成不同类型的枚举(如 YearOfBirth)有什么意义,这只会在处理属性时导致问题。使用 Any 作为类型,但有一些限制。
  • @E.YILDIRIM 像这样:[YearOfBirth]
  • @JoakimDanielson 枚举是不同已知类型的最佳答案。我不知道这个特定 json 的原因,但也许最好定义一个自定义解码器来解码它并在初始化程序中转换为 Int 。否则,枚举是最好的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
相关资源
最近更新 更多