Introducing Resilient Decoding

Hello Swift Community, a package I've been working on at Airbnb has just been open sourced!

The basic gist is that it allows you to mark properties in your Decodable types as @Resilient which allows them to gracefully recover from errors. You can then inspect those errors at the property or report on all errors encountered during decoding.

So after running this code:

struct Foo: Decodable {
  @Resilient var array: [Int]
  @Resilient var value: Int?
}
let foo = try JSONDecoder().decode(Foo.self, from: """
  {
    "array": [1, "2", 3],
    "value": "invalid",
  }
  """.data(using: .utf8)!)

foo will be a Foo where foo.array == [1, 3] and foo.value == nil . Additionally, foo.$array.results will be [.success(1), .failure(DecodingError.dataCorrupted(…), .success(3)] and foo.$value.error will be DecodingError.dataCorrupted(…) .

31 Likes

Hey George, this is really great. Going to share the link!

Great property wrapper!
I tried to implement something similar, but never found a way to catch decoding errors for missing keys.
In this comment of your implementation, you explain how you did it. That's awesome, thank you!

Is this behavior documented anywhere in the official Swift documentation?
I think it is just the behavior of Swifts method overloading resolution, but as I tried to implement my Property Wrapper I did not come up with this solution.
If it is not documented, we should definitely add it.

1 Like

Yeah, it is a bit tricky, but I think it flows logically when you think about what the synthesized init(from:) would look like if it were just written out directly. The closest thing I’ve seen to documentation was this comment in the Swift source code. I’m exploring easing more of the restrictions around this pattern in this thread.

1 Like

Very nice. I've been looking for a solution to this problem, and it's nice to see it encapsulated in a property wrapper, where I can selectively apply it to only certain properties.

Resilient Decoding has now hit 1.0, with a minor (but API-breaking) change in how errors are reported and a bit of new functionality (including resilient dictionaries):

2 Likes