Search code examples
swiftcodableintrospection

Is there a way to iterate through a Codable (e.g. each item in a JSON parse)?


Say you're decoding a huge JSON file:

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

After you parse it, on the console you simply want to see how many of each:

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

and so on, the result being cats 1,015, dogs 932, etc.

I'm too lazy to repeatedly type a line of code like this:

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

Without having to modify Examp in any way, is there a way to do something like:

for (thing) in Examp { print("\(thing string) .. \(result.(thing).count)") }

Solution

  • You can use a Mirror to reflect on the Examp, and loop through its children. You can then print the name and value of each child. To get the array's size, you can cast the value to [Any], since arrays are covariant (any type of array can be casted to [Any]).

    For example:

    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)")
    }