gpt4 book ai didi

json - 预期解码 Dictionary 但发现一个数组而不是嵌套容器

转载 作者:搜寻专家 更新时间:2023-11-01 06:27:02 24 4
gpt4 key购买 nike

因此,我尝试使用 Codable 协议(protocol)解析此 JSON: https://randomuser.me/api/?results=100

这基本上是 100 个随机用户。

这是来自解码器的我的用户类初始化器,我需要它,因为用户是核心数据模型中的一个实体:

required convenience public init(from decoder: Decoder) throws {
let managedObjectContext = CoreDataStack.sharedInstance.persistentContainer.viewContext
guard let entity = NSEntityDescription.entity(forEntityName: "User", in: managedObjectContext) else {
fatalError("Failed to decode User")
}

self.init(entity: entity, insertInto: managedObjectContext)

let container = try decoder.container(keyedBy: CodingKeys.self)
let results = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .results)
let name = try results.nestedContainer(keyedBy: CodingKeys.self, forKey: .name)
firstName = try name.decode(String.self, forKey: .firstName)
lastName = try name.decode(String.self, forKey: .lastName)

let location = try results.nestedContainer(keyedBy: CodingKeys.self, forKey: .location)
let street = try location.decode(String.self, forKey: .street)
let city = try location.decode(String.self, forKey: .city)
let postcode = try location.decode(String.self, forKey: .postcode)
address = street + ", " + city + ", " + postcode

email = try results.decode(String.self, forKey: .email)

let pictures = try results.nestedContainer(keyedBy: CodingKeys.self, forKey: .pictures)
pictureURL = try pictures.decode(String.self, forKey: .pictureURL)
}

这是有缺陷的线路:

let results = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .results)

这是完整的错误:

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))

我认为这是由于 JSON 的结构所致,它是键“结果”下的 100 个元素的数组,我认为问题可能出在将它们全部组合在一起时。我该如何处理?

最佳答案

错误很明显:results 的值是一个数组,而 nestedContainers 需要一个字典。

要解码用户数组,您需要核心数据类之外的伞形结构。

struct Root : Decodable {
let results: [User]
}

在解码 Root 时,为每个数组项调用 User 中的 init 方法。

要使用 nestedContainers,您必须将 CodingKey 分开。

这是没有 Core Data 内容的 init 方法。 postcode 可以是 StringInt

private enum CodingKeys: String, CodingKey { case name, location, email, picture }
private enum NameCodingKeys: String, CodingKey { case first, last }
private enum LocationCodingKeys: String, CodingKey { case street, city, postcode }
private enum PictureCodingKeys: String, CodingKey { case large, medium, thumbnail }

required convenience public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let nameContainer = try container.nestedContainer(keyedBy: NameCodingKeys.self, forKey: .name)
let firstName = try nameContainer.decode(String.self, forKey: .first)
let lastName = try nameContainer.decode(String.self, forKey: .last)

let locationContainer = try container.nestedContainer(keyedBy: LocationCodingKeys.self, forKey: .location)
let street = try locationContainer.decode(String.self, forKey: .street)
let city = try locationContainer.decode(String.self, forKey: .city)
let postcode : String
do {
let postcodeInt = try locationContainer.decode(Int.self, forKey: .postcode)
postcode = String(postcodeInt)
} catch DecodingError.typeMismatch {
postcode = try locationContainer.decode(String.self, forKey: .postcode)
}
let address = street + ", " + city + ", " + postcode

let email = try container.decode(String.self, forKey: .email)

let pictureContainer = try container.nestedContainer(keyedBy: PictureCodingKeys.self, forKey: .picture)
let pictureURL = try pictureContainer.decode(URL.self, forKey: .large)
}

关于json - 预期解码 Dictionary<String, Any> 但发现一个数组而不是嵌套容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53024814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com