|
I'm finding that Codable and JSONEncoder/Decoder are frustratingly close to what I need, but are missing one feature that would enable my (fairly simple!) use case... and I haven't figured out how to add this feature myself. There are a thousand articles to be found on how to make your types Codable and then serialize/deserialize to JSON. I've implemented this, and it works great with minimal effort and code. The problem showed up when I added a field to my type. The JSONDecoder then immediately refused to deserialize any existing data, and it throws an error without having done any of the deserialization work. That simply isn't acceptable. The solutions I have found involve either:
There are 3 very simple situations that happen very frequently when types are being modified:
With some careful thought/planning when making changes to the types, this simple strategy can go a LONG way to staying compatible with existing saved data, and it involves much much less code that any of the solutions (1..4) that I've found so far. It is thus very frustrating that it doesn't seem possible to tell JSONDecoder (or the compiler's decoder method generator) to simply ignore missing keys and carry on. I can think of three potential solutions, but don't know if any of them are actually possible...
Anyone have a workable solution? |
|
One possible way to reframe your problem is to consider separating the domain model from the data model. You could implement a DTO for the data model that conforms to It also has the added benefit of abstracting the rest of your code from how your data model/persistence layer works under the hood, and you could easily change persistence layers without too much overhead. Here's a pretty good article that sums of the pros of doing this I do like your idea of some sort of option for the decoder to skip missing keys, that seems pretty sensible. |
|
Yes, I know I could implement a DTO layer (it was solution #3 in my first list)... but it is a lot of code to maintain. My use case is to have a simple and easy to maintain serialization module. Duplicating or contorting all the types and providing helper functions goes directly against the principle of it. I fully understand the use cases where DTO models and the other solutions make sense (and I've done pretty much all the variations at one time or another... have been at this game for a loooong time), but sometimes just being able to serialize the data and having a less strict deserialization is really just the best solution. Unfortunately in Swift it appears this isn't currently possible, which is too bad because they are just a whisker away from one of the best solutions I've ever seen to this problem. I had been hoping to write my own wrapper around JSONDecoder, but my Swift Fu is weak and I'm not sure I could pull it off without a major investment in time that I don't really want to make currently. |
GO FURTHER, FASTER Unleash your full potential as a Swift developer with the all-new Swift Career Accelerator: the most comprehensive, career-transforming learning resource ever created for iOS development. Whether you’re just starting out, looking to land your first job, or aiming to become a lead developer, this program offers everything you need to level up – from mastering Swift’s latest features to conquering interview questions and building robust portfolios. Sponsor Hacking with Swift and reach the world's largest Swift community! |
|
I just stumbled upon this, which looks promising: https://github.com/marksands/BetterCodable Will need to verify that it does what I need and that all the property wrapping doesnt mess with the other builtin compiler behaviours I'm using (e.g. Equatable). |
|
Sounds like a file type version problem.
Maybe try this. Add a |
|
Yeah, and forcing the versioning into the code is far more work than the problem deserves. Which is why I want a simple decode policy that can tolerate changes in the format. |
|
Saw this on the Swift forums summary email, may be worth a look: https://forums.swift.org/t/introducing-resilient-decoding/35212 |
|
Thanks. It doesn't do what I want (i.e. support simple value types that are missing), but I have posted an issue to the Github project... maybe he can add that functionality. |
|
It's really annoying that we cannot easily setup default values to variables when using Decodable. Even though there are various other ways to implement an init just to make it work, it defies it's purpose of keeping it small & tidy! I'm working with an unpredictable response which might give a nil for any key and I need to initialise the model properties with various default values if it's not in the response. I find the traditional approach of parsing the dictionary into model makes more sense if you want a model with many default values. It certainly adds a bit of a boilerplate but definitely gives a finer control over default values. You can try out this - https://mavswap-swift-model-generator.herokuapp.com/ It takes in a json response and returns the models along with dictionary parsing. |
|
I share your frustration and could identify not only with the issue but also with the issues of the most common solutions. Anyway, I ran into a couple of articles that discussed using a You can find more about this on my answer to a similar stackoverflow question: https://stackoverflow.com/a/63103704/2030092 Or jump straight to the article/library that implements some useful examples: http://marksands.github.io/2019/10/21/better-codable-through-property-wrappers.html https://github.com/marksands/BetterCodable |
TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and more!
Sponsor Hacking with Swift and reach the world's largest Swift community!
This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.
All interactions here are governed by our code of conduct.
Link copied to your pasteboard.