0

I am passing a bunch of objects from a JSON but it turns out some of them have an empty string instead of a URL. My model expects a valid URL and I would rather skip the non-conforming objects than make the URL property optional.

This turns out to not be that straight-forward. Is there a built-in way to skip non-decodable objects from an array?

Alper
  • 3,424
  • 4
  • 39
  • 45

1 Answers1

2

It turns out that this is an open problem with a ticket in Swift.

I implemented the workaround as posted there on my problem in the following way:

struct AnyCodable: Codable {}

struct Trending: Codable {
  var data: [Gif]

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    var gifContainer = try container.nestedUnkeyedContainer(forKey: .data)

    var gifs = [Gif]()

    while !gifContainer.isAtEnd {
      if let gif = try? gifContainer.decode(Gif.self) {
        gifs.append(gif)
      } else {
        let skipped = try? gifContainer.decode(AnyCodable.self)
        print("Skipping one \(skipped)")
      }
    }

    self.data = gifs
  }
}
Alper
  • 3,424
  • 4
  • 39
  • 45
  • 1
    Came here to validate my own solution and found this. I can see it's been answered elsewhere, but this more succinctly answers the question. The only differences I had were this: `struct AnyDecodable: Decodable {}` and `_ = try gifContainer.decode(AnyCodable.self)` You want to remove the `try?` because you might find yourself in an infinite loop. – mc7h Sep 20 '18 at 01:12
  • You want to remove the `try?` for the line with `let skipped`? I want a handle on it to be able to print it out, so it might be better to remove the `try?` and turn the entire thing into another `if let`? – Alper Sep 20 '18 at 07:57