【问题标题】:Getting error while trying to decode json through jsondecoder尝试通过 jsondecoder 解码 json 时出错
【发布时间】:2020-08-27 00:06:10
【问题描述】:

这是我的 json 我正在尝试使用 JSONDecoder 进行解码,但由于无法做到这一点而遇到了困难。有人可以帮助我了解什么结构以及如何解码?

{
"Afghanistan": [
    {
        "city": "Kabul",
        "lat": "34.5167",
        "lng": "69.1833",
        "state": "Kābul",
        "country": "Afghanistan"
    },
    {
        "city": "Karukh",
        "lat": "34.4868",
        "lng": "62.5918",
        "state": "Herāt",
        "country": "Afghanistan"
    },
    {
        "city": "Zarghūn Shahr",
        "lat": "32.85",
        "lng": "68.4167",
        "state": "Paktīkā",
        "country": "Afghanistan"
    }
],
"Albania": [
    {
        "city": "Tirana",
        "lat": "41.3275",
        "lng": "19.8189",
        "state": "Tiranë",
        "country": "Albania"
    },

    {
        "city": "Pukë",
        "lat": "42.0333",
        "lng": "19.8833",
        "state": "Shkodër",
        "country": "Albania"
    }
]}

你建议如何解码?

我正在尝试这个

let locationData: Countries = load("Countries.json")

func load<T: Decodable>(_ filename: String) -> T {
let data: Data

guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
    fatalError("Couldn't find \(filename) in main bundle.")
}

do {
    data = try Data(contentsOf: file)
} catch {
    fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}

do {
    let decoder = JSONDecoder()
    return try decoder.decode(T.self, from: data)
} catch {
    fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
 }

struct Country: Codable, Identifiable {
var id = UUID()

let city, lat, lng: String
let state: String?
let country: String
}

typealias Countries = [String: [Country]]

但出现此错误

无法将 Country.json 解析为 Dictionary>: keyNotFound(CodingKeys(stringValue: "id", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "阿尔巴尼亚", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "没有与键关联的值 CodingKeys(stringValue: \"id\", intValue: nil) (\"id\").", 基础错误:无)):

【问题讨论】:

  • 与您的问题无关,但抛出fatalError 通常是个坏主意,尤其是在do-catch 的catch 块中。如果你真的无法从try 抛出的错误中恢复,你应该简单地使用try!。但是,在大多数情况下,这也是一个坏主意,因为如果为用户执行了 catch 块,应用程序将简单地崩溃而不会收到错误消息。最好使用assertionFailures 而不是fatalErrora,这样您可以在开发过程中及早发现错误,但用户不会遇到崩溃,而是向他们显示一般错误消息。

标签: json swift swift5 codable


【解决方案1】:

由于属性 id 不是 json 的一部分,因此您需要通过将 CodingKey 枚举添加到 Country 来定义解码器应解码的属性

enum CodingKeys: String, CodingKey {
    case city, lat, lng, state, country
}

CodingKey 枚举还让您有机会为您的结构属性使用更好的名称(如果您愿意)并将它们在枚举中映射到 json 键。

struct Country: Codable, Identifiable {
    var id = UUID()

    let city: String
    let latitude: String
    let longitude: String
    let state: String?
    let country: String

    enum CodingKeys: String, CodingKey {
        case city
        case latitude = "lat"
        case longitude = "lng"
        case state, country
    }
}

【讨论】:

    【解决方案2】:

    这是错误的相关部分:keyNotFound(CodingKeys(stringValue: "id", intValue: nil)。它告诉您它正在每个 JSON 对象中寻找一个“id”键,但没有找到它。

    它正在寻找一个 id,因为结构的 Codable 协议的默认实现试图反序列化您定义的所有属性。您定义了一个 var id 属性,所以它正在寻找它。

    由于您不想反序列化 id 属性,因此您需要自定义结构,使其不使用默认实现。如何做到这一点的文档在这里:Encoding and Decoding Custom Types

    在您的情况下,您只需要在结构中定义一个 CodingKeys 枚举,以便它知道要查找哪些键:

    enum CodingKeys: String, CodingKey {
        case city, lat, lng, state, country
    }
    

    【讨论】:

      猜你喜欢
      • 2022-10-08
      • 1970-01-01
      • 2013-03-04
      • 1970-01-01
      • 1970-01-01
      • 2018-11-08
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多