Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I decode JSON in Swift when it's an array and the first item is a different type than the rest?

Say the JSON looks like this:

[
    {
        "name": "Spot",
        "breed": "dalmation"
    },
    {
        "color": "green",
        "eats": "lettuce"
    },
    {
        "color": "brown",
        "eats": "spinach"
    },
    {
        "color": "yellow",
        "eats": "cucumbers"
    }
]

Where the first item in the JSON responses you get back from the API are always a dog, and all the ones after that are always turtles. So item 0 is dog, items 1 through N-1 are turtles.

How do I parse this into something that I can read, like:

struct Result: Codable {
    let dog: Dog
    let turtles: [Turtle]
}

Is it possible?

like image 292
Doug Smith Avatar asked Dec 13 '22 16:12

Doug Smith


1 Answers

You can implement a custom decoder for your Result struct.

init(from decoder: Decoder) throws {
    var container = try decoder.unkeyedContainer()

    // Assume the first one is a Dog
    self.dog = try container.decode(Dog.self)

    // Assume the rest are Turtle
    var turtles = [Turtle]()

    while !container.isAtEnd {
        let turtle = try container.decode(Turtle.self)
        turtles.append(turtle)
    }

    self.turtles = turtles
}

With a minor amount of work you could support the Dog dictionary being anywhere within the array of Turtle dictionaries.

Since you declared that your structs are Codable and not just Decodable, you should also implement the custom encode(to:) from Encodable but that is an exercise left to the reader.

like image 70
rmaddy Avatar answered Dec 18 '22 11:12

rmaddy