gpt4 book ai didi

json - Swift 无法使用枚举初始化器访问 JSON 响应的一部分

转载 作者:行者123 更新时间:2023-11-30 10:48:35 28 4
gpt4 key购买 nike

我无法访问 JSON 响应的一部分。

(部分)来源:

{
"time":1552726518,
"result":"success",
"errors":null,
"responce":{
"categories":{
"1":{
"nl":{
"name":"New born",
"description":"TEST",
"children":[
{
"name":"Unisex",
"description":"TESTe",
"children":[
{
"name":"Pants",
"description":"TEST",
"children":false
}
]
}
]
}
}
}
}
}

方法正如您所看到的,源可以有多个类别。单个类别将有“名称”、“描述”,并且可能有“子级”。 child 会有“名字”、“描述”,也可能有“ child ”。这可能会无休无止。如果没有 child ,SJON 语句为“假”

我使用的网站:https://app.quicktype.io生成一堆垃圾代码来解析 JSON。我修改了结果,因为网站不知道 children 可以走不完:

struct ProductCategories: Codable {
let time: Int?
let result: String?
let errors: [String]?
let responce: ProductCategoriesResponce?

init(time: Int? = nil, result: String? = nil, errors: [String]? = nil, responce: ProductCategoriesResponce? = nil) {

self.time = time
self.result = result
self.errors = errors
self.responce = responce
}
}

struct ProductCategoriesResponce: Codable {
let categories: [String: Category]?
}

struct Category: Codable {
let nl, en: Children?
}

struct Children: Codable {
let name, description: String?
let children: EnChildren?
}

enum EnChildren: Codable {
case bool(Bool)
case childArray([Children])

init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Bool.self) {
self = .bool(x)
return
}
if let x = try? container.decode([Children].self) {
self = .childArray(x)
return
}
throw DecodingError.typeMismatch(EnChildren.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for EnChildren"))
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .bool(let x):
try container.encode(x)
case .childArray(let x):
try container.encode(x)
}
}
}

我可以使用以下方法解码数据:

productCategories = try JSONDecoder().decode(ProductCategories.self, from: jsonData!)

这部分工作正常。我可以访问“New Born”,但无法访问他的 child 。我花了很长时间寻找我尝试过的答案。在这里与大家分享的内容太多了。我期望获得的访问权限是:

 if let temp = productCategories.responce?.categories?["\(indexPath.item)"]?.nl?.children! {
let x = temp(from: Decoder)

但这会给我一个错误:“无法调用非函数类型‘EnChildren’的值”

还有类似的代码:

  let temp1 = productCategories.responce?.categories?["\(indexPath.item)"]?.nl?.children

不会带我去任何地方。

那么,有什么想法吗?谢谢。

最佳答案

首先:如果您负责服务器端,请为叶子级发送 null 或省略 key ,而不是发送 false。它使解码过程变得更加容易。

app.quicktype.io 是一个很棒的资源,但我不同意它的建议。

我的解决方案使用带有自定义初始值设定项的常规结构Children。该结构体可以递归使用。

key children是有条件解码的。首先解码[Children],失败时解码Bool并将children设置为nil或移交错误。

并且我尽可能多地将结构成员声明为非可选

struct Response: Decodable {
let time: Date
let result: String
let errors: [String]?
let responce: ProductCategories
}

struct ProductCategories: Decodable {
let categories: [String: Category]
}

struct Category: Decodable {
let nl: Children
}

struct Children: Decodable {
let name, description: String
let children : [Children]?

private enum CodingKeys : String, CodingKey { case name, description, children }

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
description = try container.decode(String.self, forKey: .description)
do {
children = try container.decode([Children].self, forKey: .children)
} catch DecodingError.typeMismatch {
_ = try container.decode(Bool.self, forKey: .children)
children = nil
}
}
}

在根对象中,如果您指定适当的日期解码策略,则键 time 可以解码为 Date

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
let result = try decoder.decode(Response.self, from: jsonData!)

例如,您可以使用

访问名称 Unisex
result.responce.categories["1"]?.nl.children?[0].name

关于json - Swift 无法使用枚举初始化器访问 JSON 响应的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55200773/

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