Encoding and decoding JSON in Swift

aka “How to decode response from a JSON API”

Import the Foundation library. This will also work if SwiftUI or UIKit or imported.

import Foundation

Define a struct to represent the JSON data

struct Dog: Codable {
    var name: String
    var age: Int
}

The struct should use the Codable protocol. This is required both for encoding and decoding.

Decoding from JSON

The following is the JSON used in the example.

let json = """
{"name": "Tommy", "age": 6}
"""

Create a Data object to store the JSON data

let data = Data(json.utf8)

The example uses JSON input from a variable. API responses will be Data objects, so they don't have to be converted into a Data object again.

Initialize a JSON decoder

let decoder = JSONDecoder()

Decode the JSON into an object

let decoder = decoder.decode(Dog.self, from: data)

The Xcode will warn about this expression throwing. So we'll have to wrap it with a try.

let decoder = try? decoder.decode(Dog.self, from: data)

decoder will now be a JsonResponse object and will contain the fields x and y

Encoding to JSON

Represent a new dog.

let dog = Dog(name: "Peggy", age: 3)

Define an encoder

let encoder = JSONEncoder()

Encode the dog and ofcourse wrap it with a try.

let json = try encoder.encode(dog)

The result will be a Data object. The response can be verified by converting it to String.

print(String(data: encoded_json, encoding: .utf8)!)

Stuff to know

In the Dog struct, both name and age are defined as mandatory properties. This means that the intializer for Dog will expect both the properties to be passed to the initializer when creating the object.

If we expect JSON responses from APIs to be containing optional fields, then it is better to make the properties optional too. Example below indicates that the age field is optional.

struct Dog: Codable {
    var name: String
    var age: Int?
}