The best way to encode and decode JSON in Swift4

Most of mobile apps interact at some point with remote services, fetching data from an api, submitting a form… Let’s see how to use Codable in Swift to easily encode objects and decode JSON in couple lines of codes.

Since Xcode9, two new protocols were introduced to facilitate this work serialisation and deserialisation: Encodable and Decodable. Both defining a JSON representation of our objects.

Here is the JSON representation of a simple object User, let’s see how to deserialise those data into an object.

{
    "id": 13,
    "firstname" : "John",
    "lastname" : "Doe",
    "email" : "john.doe@lost.com"
}

Decoding JSON into object

I use a struct type to represent my object and include the protocol Decodable to allow deserialisation.

struct User : Decodable {
	let id : Int
	let firstname : String
	let lastname : String
	let email : String
}

Now we’re ready to decode it using JSONDecoder.

// assuming our data comes from server side
let jsonString = "{ \"id\": 13, \"firstname\" : \"John\", \"lastname\" : \"Doe\", \"email\" : \"john.doe@lost.com\" }"
let jsonData = jsonString.data(using: .utf8)!

do {
    let jsonDecoder = JSONDecoder()
    let user = try jsonDecoder.decode(User.self, from: jsonData)
    print("Hello \(user.firstname) \(user.lastname)")
} catch {
    print("Unexpected error: \(error).")
}

Pretty easy right? Let’s see how to serialise it now.

Encoding object into JSON

First, we need update our struct to allow encoding. To do so, we just need to include protocol Encodable.

struct User : Encodable, Decodable {
 ...
}

Our object is ready to be serialised back to JSON. We follow the same process as before, using JSONEncoder this time. In that case, I’ll also convert the data into a String to be sure it’s working

// assuming we have an object to serialise
var newUser = User(id: 15, firstname: "Bob", lastname: "Sponge", email: "bob@sponge.com")

do {
    let jsonEncoder = JSONEncoder()
    let jsonData = try jsonEncoder.encode(newUser)
    let jsonString = String(data: jsonData, encoding: .utf8)
    print(jsonString) // result : "{"email":"bob@sponge.com","id":13,"lastname":"Sponge","firstname":"Bob"}"
} catch {
    print("Unexpected error: \(error).")
}

That’s still pretty easy! So what is Codable all about?

Well, Codable, is just alias of Encodable and Decodable protocols as you can see in it’s definition

public typealias Codable = Decodable & Encodable

If you don’t want your JSON keys to drive your naming, you can still customise them using CodingKeys. Described as an enum, it will automatically be picked up while encoding / decoding

struct User : Codable {
    var id : Int
    var firstname : String
    var lastname : String
    var email : String?

    // keys
    private enum CodingKeys: String, CodingKey {
        case id = "user_id"
        case firstname = "first_name"
        case lastname = "family_name"
        case email = "email_address"
    }
}

To go further

Now that we mostly covered the basics of encoding and decoding JSON in Swift, here is extra information that you should keep in mind while using it.

In our example, encoding works great because my JSON has only primitive variables (strings, numbers, etc). If you have more complex objects which include relationship with others, you need to be sure all of them implement both protocols to avoid any issues.

Some built-in types are already implementing Codable protocol, like Array, Dictionary or Optional. For the last one is particularly handy when it comes to missing field from your JSON or equal to null, it would trigger an error except if your object without.

On the other hand, Struct type comes with default constructors that are automatically used in those context. If my object is a Class, we would need to re-implement Encodable and Decodable and their respective methods encode(to encoder: Encoder) and init(from decoder: Decoder).


In conclusion, we’ve seen how to encode and decode JSON data in Swift 4 using Codable protocols and how to customize our object keys represent more complex data structure.

Happy coding!

Resources

© 2023 Benoit Pasquier. All Rights Reserved
Author's picture

Benoit Pasquier

Software Engineer 🇫🇷, writing about career development, mobile engineering and self-improvement

ShopBack 💰

Singapore 🇸🇬