json - 如何扁平化嵌套的 JSON 结构
问题描述
嵌套的 JSON
{
"items": [{
"track": {
"name": "Never Gonna Give You Up"
}
}]
}
我希望它看起来像这样
{
"tracks": [{
"name": "Never Gonna Give You Up"
}]
}
我试过的
struct TrackResponse: Decodable {
let tracks: [Track]
enum CodingKeys: String, CodingKey {
case tracks = "items"
}
enum TrackKeys: String, CodingKey {
case track
}
init(from decoder: Decoder) throws {
let outerContainer = try decoder.container(keyedBy: CodingKeys.self)
let trackContainer = try outerContainer.nestedContainer(keyedBy: TrackKeys.self,
forKey: .tracks)
self.tracks = try trackContainer.decode([Track].self, forKey: .track)
}
struct Track: Decodable {
var name: String
}
}
我收到此错误
预期解码 Dictionary<String, Any> 但找到了一个数组。
更新
我创建了一个具有更多上下文和一些更改的新问题,并通过遵循@vadian 的回复最终达到了我的目标。
检查一下,看看它是否也能帮助你:将 具有细微差异的 JSON 结构解码为一种格式
解决方案
嵌套容器为您的代码增加了一定程度的复杂性,您可以通过使用普通的旧可解码器来避免这种情况。
因此,只需声明一个(私有)结构Item
,在 的初始化程序中对其进行解码TrackResponse
,然后从那里提取轨道:
struct TrackResponse: Decodable {
var tracks: [Track]
enum CodingKeys: String, CodingKey {
case items
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let items = try container.decode([Item].self, forKey: .items)
tracks = items.map(\.track)
}
struct Track: Decodable {
var name: String
}
private struct Item: Decodable {
var track: Track
}
}
我的观点是,您应该尝试尽可能多地模仿 JSON 结构,这将更容易应对 JSON 结构的未来变化。如果需要用另一种形式表示数据,在解码成功后进行后处理。
我自己,我会走得更远,简化整个响应代码:
struct TrackResponse: Decodable {
var items: [Item]
struct Track: Decodable {
var name: String
}
struct Item: Decodable {
var track: Track
}
}
,然后在收到响应后简单地提取曲目:
let tracks = response.items.map(\.track)
您编写的代码越少,您引入错误的机会就越小;)
推荐阅读
- swift - 此代码示例中“didSet”的用途是什么?
- visual-studio - NuGet 在项目根目录中包含任意文件
- airflow - Airflow 成功后多次重新运行单个任务
- php - 是否可以使用谷歌图表创建每列有多个类别的图形?
- hibernate - Override hibernate 物理命名策略 | @Column 不工作
- python-3.x - Flask 应用程序中的 FloatField 条目出现问题
- javascript - 按钮单击上的 javascript 功能有时有效
- c++ - 如何修复超过 1 分钟规则的 Collatz 序列码?
- reactjs - 反应选择没有选择选项
- python - 熊猫:选择最后“N”列