Swift: How to Convert a Dictionary to JSON

Updated: May 8, 2023 By: Khue Post a comment

Overview

A Swift dictionary is a collection of unordered and unique key-value pairs. JSON is a lightweight and human-readable format for exchanging data.

If you want to convert a dictionary into JSON, this dictionary must conform to the Encodable or the Codable protocol. For example, a dictionary with values of type String, Int, Bool, or any other standard library type that conforms to Codable protocol can be converted to JSON. However, a dictionary with values of type UIImage, UIView, or any other custom type that does not conform to Codable protocol cannot be converted to JSON unless you implement the required methods for encoding and decoding.

In Swift, you can turn a dictionary into JSON by using the JSONSerialization class or the JSONEncoder class. Let’s unveil them in this article, one by one.

Using the JSONSerialization class

The class brings to the table a method named JSONSerialization.data(withJSONObject:options:), which can convert a dictionary into JSON data (a Data object). This method takes a dictionary (or any other Foundation object that can be converted to JSON) and an optional writing option (such as .prettyPrinted for formatting the output). It returns a Data object that contains the JSON representation of the dictionary. When calling the method, you should use a try-catch block to handle potential errors.

To convert the JSON data into a JSON string, just use theString(data:encoding:) initializer. This initializer takes a Data object and an encoding (such as .utf8 for Unicode) and returns an optional String object that contains the JSON text.

An example is worth more than a thousand words:

import Foundation

// a dictionary of people and their ages
let people = [
    "Wolf Man": 999,
    "Dracula": 100,
    "Mummy": 1500,
    "Sling Academy": 10
]

do {
    // here jsonData is the dictionary encoded in JSON data
    let jsonData:Data = try JSONSerialization.data(
        withJSONObject: people,
        options: .prettyPrinted
    )

    // get a JSON string from jsonData object
    let jsonString:String = String(data: jsonData, encoding: .utf8)!
    print(jsonString)
} catch {
    print(error.localizedDescription)
}

Output:

{
  "Wolf Man" : 999,
  "Mummy" : 1500,
  "Sling Academy" : 10,
  "Dracula" : 100
}

Let’s take a closer look at the .prettyPrinted option. This one is a writing option that specifies that the output uses white space and indentation to make the resulting data more readable. If this option isn’t set, the serialization generates the most compact possible JSON representation (a kind of one-long-line text without white spaces) like this:

{"Dracula":100,"Mummy":1500,"Wolf Man":999,"Sling Academy":10}

If you print jsonData (an instance of the Data class) instead of jsonString, you will see the number of its bytes.

Using the JSONEncoder class

The JSONEncoder.encode(_:) method can take a dictionary that conforms to the Encodable or the Codable protocol and returns a Data object that contains the JSON representation of the input dictionary.

Example:

import Foundation

let dict = [
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
]

do {
    // here jsonData is the dictionary encoded in JSON data
    let jsonData = try JSONEncoder().encode(dict)

    // here jsonString is the dictionary converted to JSON string
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
} catch {
    print(error.localizedDescription)
}

Output:

{"key1":"value1","key3":"value3","key2":"value2"}