此帖子与previous post I made有关。我希望映射以下嵌套字典:
["A": [["A1": ["A11", "A12"]], ["A2": ["A21", "A22"]]],
"B": [["B1": ["B11", "B12"]], ["B2": ["B21", "B22"]]]
]
转换为递归结构:
Item(title:"",children:
[Item(title:"A",children:
[Item(title:"A1", children:
[Item(title:"A11"),Item(title:"A12")]
)]),
Item(title:"B",children:
[Item(title:"B1"),Item(title:"B2")]
)]
)
与
struct Item: Identifiable {
let id = UUID()
var title: String
var children: [Item] = []
}
为了进行实验,我从[“ A”:[[“ A1”:[“ A11”]]]]开始,并制作了一个json字符串:
let json1: String = """
{"title": "", "children":[{"title": "A",
"children": [{"title": "A1",
"children": [{"title": "A11"}]
}]
}]
}
"""
let decoder = JSONDecoder()
let info = try decoder.decode(Item.self, from: json.data(using: .utf8)!)
print(info)
仅当我在最后一个节点中包含“ children”:[]时,此方法才有效:
let json2: String = """
{"title": "", "children":[{"title": "A",
"children": [{"title": "A1",
"children": [{"title": "A11", "children": []}]
}]
}]
}
"""
我需要做些什么才能使json1字符串起作用,以便即使没有孩子的输入,它也将采用[]的默认值?
答案 0 :(得分:0)
您必须提供自定义init(decoder:)
来处理这种情况。处理此问题将需要您使用decodeIfPresent
容器的JSONDecoder
API,并尝试仅在存在值的情况下进行解码,并在条件失败时提供默认值。方法如下:
extension Item: Codable {
enum CodingKeys: String, CodingKey {
case title, children
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
children = try container.decodeIfPresent([Item].self, forKey: .children) ?? []
}
}
答案 1 :(得分:0)
一种方法是使children
为可选,并使用计算属性访问它。在children
为nil
的情况下,calculated属性可以返回一个空数组。
struct Item: Identifiable, Decodable {
let id = UUID()
var title: String
private var privateChildren: [Item]?
var children: [Item] {
return self.privateChildren ?? []
}
enum CodingKeys: String,CodingKey {
case title
case privateChildren = "children"
}
}
我使用了CodingKeys
枚举,以便您可以在JSON和代码中保留相同的名称,但是如果您在JSON或代码中更改属性名称,则可以避免这种情况。>