有没有办法迭代 Codable(例如 JSON 解析中的每个项目)?

问题描述 投票:0回答:1

假设您正在解码一个巨大的 JSON 文件:

struct Examp: Codable {
  let Cats: [CatsItem]
  let Dogs: [DogsItem]
  let Horses: [HorsesItem]
  .. forty more
}

解析完后,在控制台上您只想查看每个有多少:

print("cats .. \(result.Cats.count)")
print("dogs .. \(result.Dogs.count)")

以此类推,结果是猫 1,015,狗 932,等等

我懒得重复敲这样一行代码:

print("cats .. \(result.Cats.count)")

无需以任何方式修改

Examp
,有没有办法做类似的事情:

for (thing) in Examp { print("\(thing string) .. \(result.(thing).count)") }
swift5 codable introspection
1个回答
0
投票

您可以使用

Mirror
来反映
Examp
,并循环遍历其子项。然后您可以打印每个孩子的姓名和价值。要获取数组的大小,您可以将值转换为
[Any]
,因为数组是协变的(任何类型的数组都可以转换为
[Any]
)。

例如:

struct Example: Codable {
    let cats: [String]
    let dogs: [String]
    let horses: [String]
}

let example = Example(cats: [""], dogs: ["", ""], horses: ["", "", ""])
let mirror = Mirror(reflecting: example)
for (name, value) in mirror.children {
    guard let name, let array = value as? [Any] else { continue }
    print("\(name) .. \(array.count)")
}

或者,编码为 JSON,然后使用旧的

[String: Any]
API 将其转换为
JSONSerialization
,就像 这个答案 所做的那样。然后再次转换为
[Any]
以获得数组。

// from the linked answer
extension Encodable {
    var dictionary: [String: Any]? {
        guard let data = try? JSONEncoder().encode(self) else { return nil }
        return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
    }
}

let example = Example(cats: [""], dogs: ["", ""], horses: ["", "", ""])
guard let dict = example.dictionary else { return }
for (key, value) in dict {
    guard let array = value as? [Any] else { continue }
    print("\(key) .. \(array.count)")
}
© www.soinside.com 2019 - 2024. All rights reserved.