All About Codable in Swift (Part 1)

In this blog we will cover

  1. Why we need Codable (Background)
  2. What is Codable, Encodable and Decodable
  3. Decode plain json to Swift custom model and vice versa
  4. Coding Keys (Keys you don’t want to parse)
  5. Keys Exists in json but not in the Model
  6. Key in model can exists or not in your json
  7. Model and json with different structure keys (Decoding)
  8. Model and json with different structure keys (Encoding)
  9. Custom Decoding With Key may or maynot exists in Json
  10. Working with Type Mismatch
https://learnappmaking.com/codable-json-swift-how-to/

Background

Every application talks to the server and use the response to display data. If your application is in swift they will use the Swift data type (Swift datatype compose object) and your server is using the Java data type so there should be some standardize data type that both know so they can talk to each other. To solve this problem we have two most common data interchange format JSON and XML

Codable

Introduced in Swift 4, Codable in Swift is used to encode and decode custom data formats, such as JSON, to native Swift objects and vice versa.Codable is actually a type alias that combines two protocols — Encodable and Decodable

Encodable Protocol

Purpose is to convert Swift datatype to Json format

Decodable Protocol

Purpose is to convert Json format to Swift datatype

Getting Started

As shown in Figure 1 we did a few things

  1. Created a Swift datatype compose object we called it custom data Type and we conform to Codable protocol
  2. Created JSONDecoder object facilitates the decoding of JSON into semantic types (type conforming to Decodable protocol). That’s why our . custom type conforming to Codable protocol. Codable is a type alias for the `Encodable` and `Decodable` protocols.
  3. decoder.decode converted json into custom type as shown in Figure 1.
Figure 1

As shown in Figure 2 we encode custom data type to json object

Figure 2

Let’s say server is sending different keys . name key is updated with the nameUp in response object, This means that the field names in the JSON will no longer match up with the property names in your type and it is giving keyNotFound error and application will crash.

Figure 3

You can define custom coding keys to supply coding names for your properties. Now it expect nameUp key from json and it value will be store on name field of the User data type

Figure 4

If your expect same key in json then you don’t need to provide enum rawvalue because raw value for a particular enumeration case is always the same

CodingKeys is the special enum mentioned above. It conforms to CodingKey and has String raw values.

Figure 5

Keys you don’t want to parse

If this enum exists, only the cases present here will be used for encoding and decoding, so even if your property doesn’t require mapping. As shown in Figure 6 notToParseType key is coming in json but it doesn't decode since we didn't specify in our enum

Figure 6

If you specify case and you don’t have in your stored property of the model it will throw an error. Case you add in enum should contain in your model

Figure 7

Keys Exists in json but not in the Model

As shown in Figure 8 Decoder take model key and search in json if it found all the key it created a model and don’t look additional field in json. So in this case it will not crash the application

Figure 8

Key in model can exists or not in your json

As shown in Figure 9 keyExistorNot may or maynot come in json so we make this property as an optional or assign some initial value. In this way our decoding will not fail

Figure 9

As shown in Figure 10 our model is hierarchical and json we expect is flat so how can we parse it

Figure 10

Model and json with different structure keys (Decoding)

Now json doesn’t match with your model structure, so you need to write our own decoding logic and describe how to decode each User and company stored property.

As shown in Figure 11 our json is flat where companyName and companyId are coming in flat structure but in our model we don’t have this property instead of this we have another custom model Company . Inside “company” were two more keys, “name” and “id”, so we created CompanyCodingKeys for that few things to note

  1. By writing your own decoder you can specify container in our case we first created container with CodingKeys and we only decode name,id and type from json Then we created CompanyCodingKeys and we expect companyName and companyId in json since it exists in enum compiler is happy
Figure 11

As shown in Figure 12 we removed custom decoder and enum and want automatic decoding of codable it failed because it expect all non-optional key to be present in json

Figure 12

Rule of Thumb 1:

Decoder by default looks CodingKeys enum and try to give initial value if succeed it will not throw any error

As shown in Figure 13 decoder list down all the enum keys in our case name, id , type , company and notToParse and find keys in json and it found name, id and type now it takes value from json and initialize these property. It didn’t able to find company and notToParse properties in json , it first check whether it is optional if it is optional it assign nil and if it not optional it check whether it has some default value if that not the case it will throw an error. In our case these two properties have default value so it will not throw an error

Figure 13

Model and json with different structure keys (Encoding)

As shown in Figure 14 server expecting flat json since our model is hierarchical it created hierarchical json company and in that use the same name property as a key

Figure 14
Figure 15

As shown in Figure 16 we created a flat json from hierarchical model structure using custom encoding

Figure 16

Custom Decoding With Key may or maynot exists in Json

As shown in Figure 17 we specified mayExists as an optional but it failed since we are decoding in custom decoder and it expect key to be there

Figure 17

As shown in Figure 18 we expect decodable to be optional in our custom decodable implementation instead it is failing because it expect this property from json

Figure 18

To solve his problem we have a method decodeIfPresent as name suggest it will decode if key exists in json.

decodeIfPresent → Decodes a value of the given type for the given key, if present.This method returns `nil` if the container does not have a value

Figure 19

As shown in Figure 20 if key exists in json but with null value your decoding will be failed. There are two solutions for this problem either you can use decodeIfPresent or expect decoding can return nil value as shown in Figure 21

Figure 20
Figure 21

Working with Type Mismatch

As shown in Figure 22 company model Id we expected Int but server is sending String

Figure 22

We fix this issue by decode it as String and type cast it as Int . This is also the reason we need to implement our own custom decoder

Figure 23

Useful Links

https://www.swiftbysundell.com/basics/codable/https://www.swiftbysundell.com/basics/codable/