Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
Ever tried to parse JSON in swift? I know! right, the sheer magnitude of boilerplate with so many nil checks makes it a really bad experience.
I am here to provide you a solution to this problem with the newly introduced Swift 4, with it Apple has finally answered the question of parsing JSON painlessly.
Letâs start with the basics
Letâs take a basic JSON structure
Our swift mapping model will look something like this:
And to convert this JSON data to our model, this is literally all the code that we have to write
You can encode this model to JSON as well
Great!! isnât it?
I have marked the Person model as Codable, which is a combination of two unidirectional protocols Encodable & Decodable. So, if you only want to encode or decode, you can just adopt the appropriate protocol.
But, Codable comes with default implementation and you can adopt this protocol to get free implementation.
Thereâs a catch! Name of the variable in your model should match the key name in JSON.
Whaaaat⊠Lifeâs not fair, most APIs are based on snake case naming đą. Well, relaxâŠ
Working with customised key names
Key names are automatically generated by the compiler in a CodingKeys enumeration which conforms to CodingKey protocol. It defines how we can connect a property to a value.
So, to customise the key, weâll have to write our own implementation of CodingKeys and there we can provide String values for keys that you want to change.
Letâs take an example, consider this JSON
Hereâs how our model will look like
Well, thatâs it đđ»
Swift Encoder & Decoder use this CodingKeys enum as a lookup and matches the corresponding JSON keys to Model variables.
Also, since String enums are implicitly assigned raw values as each caseâs name, we only need to provide raw values for problematic cases.
But wait, what about Objects or Wrappers?
Objects and Wrappers
Letâs assume our JSONÂ is
Here, you have to make sure your Film object also conforms to Codable and thatâs basically it. Here, have a looksee.
What about root level arrays? Any easy way to decode if our JSON comes wrapped in an array. Well, ÂŻ\_(ă)_/ÂŻ take this JSON for instance.
All you have to write is this,
đŹ
How to handle Dates?
Well, get your life together ^.~
In swift though,
Since JSON has no data type to represent dates, that information is serialised in either ISO 8601, the number of seconds from reference date or some custom format. It was then handled using String and converted to a Date using DateFormatter. Ugh! IÂ Know!!
The good news is, now you can decode the date string from JSON right into the model using JSONDecoder. Checkity check it
Same goes for Encoder too. Apart from these strategies, you can even use custom encoder and decoder
custom((Decoder) throws -> Date) //For Decodingcustom((Date, Encoder) throws -> Void) //For Encoding
I know, I know, an example would be good. Here
Handling Swift.Data and URL!!
You might encounter Data in your JSON as base64 encoded strings and to handle this JSONEncoder gives these two strategies
.base64.custom((Data, Encoder) throws -> Void)
Same goes for JSONDecoder too.
When it comes to URL, just replace the data type from String to URL and thatâs it
Handling Floating Point??
Well, this doesnât happen often but sometimes JSON might contain an invalid âNaNâ, â+Infinityâ or â-Infinityâ. These are not recognised in Swift!
Normally your decoder will throw an error if you do not provide an implementation to handle this non-conformity. Just write
Similarly, this can be done with JSONEncoder as well.
Wait, but what about unidirectional conformance? There is no default implementation for that! Iâll show you, itâs really cool
Unidirectional Encodable & Decodable
Sometimes you might just want to conform to either Encodable or Decodable and work from there. But, before that, we need to understand the concept of containers. These are some types of containers:
- Keyed Container: This is essentially a dictionary type and contains key-value pairs.
- Unkeyed Container: represents a wrapper, essentially an array.
- Single Value Container: represents a raw type denoted by a key.
Now, all you have to do is guide the compiler how you want the data to be decoded and thatâs it. Have a look
Letâs assume we have the following JSON, now we can make a nested model or we can do this:
Since movie name and director name comes nested in a container, we can use the nested container property of decoder to extract the values and use in corresponding keys. Here, I am extracting the "film" object to the filmInfo container and then use it to decode values in movieName and director keys.
Similarly, for Encoder, we take our movieName and director keys and encode them in the filmInfo container and this will return the exact JSON as before. Thatâs the power of coding keys.
Handle dictionary and enum?
You wonât need this as often but you can parse your JSON in a dictionary or an enumeration too.
Dictionary
Consider the following JSON
Can you identify any similarity between these objects? Both "Death Star" & "Millennium Falcon" nests a model inside. Letâs see what we can make of this
Enumerations
Letâs take in a straight dive with this JSON
Yeah! thatâs one weird JSON, but itâll do the trick. Letâs have a look at our code
Congrats! You have successfully parsed your JSON to enum cases.
There are some errors to be handled :)
Till now, all we used was a simple catch as a panacea, but there are some known cases that we can catch and handle accordingly.
- DecodingError.dataCorrupted(DecodingError.Context): This could occur if the data you received is not JSON, maybe an HTML or an API error. You will get this information using the context.
- DecodingError.keyNotFound(CodingKey, DecodingError.Context): This occurs if a required key is not found in JSON, CodingKey will give you the problematic key and context will give you information about where and what happened.
- DecodingError.typeMismatch(Any.Type, DecodingError.Context): This occurs if there is a type mismatch between the keys. You can use the context and type to know what happened.
Have a look
Same goes for Encoder, these errors are very helpful in giving you the flexibility to adapt to certain situations and handle them appropriately.
Further Learning
There is nothing better than the WWDC 2017 resource themselves. HereâŠ
- What's New in Foundation - WWDC 2017 - Videos - Apple Developer
- Using JSON with Custom Types | Apple Developer Documentation
Conclusion
Whoot! This was a looong ride, but this is the future of Swift JSON parsing. Comments/Suggestions are welcome :)
AdiĂłs (-Ï-ăMay the force be with you
Swift Codability was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.