Skip to content

How to encode and decode JSON data in Swift

Codable

Swift Codable is a powerful feature introduced in Swift 4 that simplifies the process of encoding and decoding JSON data.

With Codable, you can easily convert Swift objects to data representations and vice versa, without having to write complex serialization and deserialization code.

Define Data Representation Model

swift
public struct Claims: Codable {
    public var sub: String?
    public var name: String?
    public var iat: Date?
}
public struct Claims: Codable {
    public var sub: String?
    public var name: String?
    public var iat: Date?
}

Convert JSON Data to Data Model

swift
let str = """
{
  "sub" : "123456790",
  "name" : "John Doe",
  "iat" : 1516239022
}
"""
let data = Data(str.utf8)

let jsonDecoder = JSONDecoder()
jsonDecoder.dateDecodingStrategy = .secondsSince1970
do {
    let claims = try jsonDecoder.decode(Claims.self, from: data)
    print(claims)
} catch {
    print(error)
}
let str = """
{
  "sub" : "123456790",
  "name" : "John Doe",
  "iat" : 1516239022
}
"""
let data = Data(str.utf8)

let jsonDecoder = JSONDecoder()
jsonDecoder.dateDecodingStrategy = .secondsSince1970
do {
    let claims = try jsonDecoder.decode(Claims.self, from: data)
    print(claims)
} catch {
    print(error)
}

Convert Data Model to JSON Data(String)

swift
let claims = Claims(sub: "123456790",name: "John Doe", iat: Date.now)
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes]
do {
    let data = try encoder.encode(claims)
    let str = String(decoding: data, as: UTF8.self)
    print(str)
}catch{
    print(error)
}
let claims = Claims(sub: "123456790",name: "John Doe", iat: Date.now)
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes]
do {
    let data = try encoder.encode(claims)
    let str = String(decoding: data, as: UTF8.self)
    print(str)
}catch{
    print(error)
}

outputFormatting values:

  • .prettyPrinted: The output formatting option that uses ample white space and indentation to make output easy to read.
  • .sortedKeys: The output formatting option that sorts keys in lexicographic order.
  • .withoutEscapingSlashes: The output formatting option specifies that the output doesn’t prefix slash characters with escape characters.

JSONSerialization

If you want to parse JSON by hand rather than using Codable, iOS has a built-in alternative called JSONSerialization and it can convert a JSON string into a collection of dictionaries, arrays, strings and numbers in just a few lines of code.

Convert JSON Data to JSON Object

swift
let str = """
{
  "sub" : "123456790",
  "name" : "John Doe",
  "iat" : 1516239022
}
"""
let data = Data(str.utf8)

do {
    if let jsonObject = try JSONSerialization.jsonObject(with: data, options: [.mutableContainers]) as? [String:Any] {
        print(jsonObject)
    }
} catch {
    print(error)
}
let str = """
{
  "sub" : "123456790",
  "name" : "John Doe",
  "iat" : 1516239022
}
"""
let data = Data(str.utf8)

do {
    if let jsonObject = try JSONSerialization.jsonObject(with: data, options: [.mutableContainers]) as? [String:Any] {
        print(jsonObject)
    }
} catch {
    print(error)
}

options values:

  • .mutableContainers: Specifies that leaf strings in the JSON object graph are mutable.
  • .fragmentsAllowed: Specifies that the parser allows top-level objects that aren’t arrays or dictionaries.
  • .json5Allowed: Specifies that reading serialized JSON data supports the JSON5 syntax.
  • .topLevelDictionaryAssumed: Specifies that the parser assumes the top level of the JSON data is a dictionary, even if it doesn’t begin and end with curly braces.

Convert JSON Object to JSON Data(String)

swift
let jsonObject:[String:Any] = ["name": "John Doe", "sub": "123456790", "iat": 1516239022]

do {
    let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted,.withoutEscapingSlashes])
    let str = String(decoding: data, as: UTF8.self)
    print(str)
}catch{
    print(error)
}
let jsonObject:[String:Any] = ["name": "John Doe", "sub": "123456790", "iat": 1516239022]

do {
    let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted,.withoutEscapingSlashes])
    let str = String(decoding: data, as: UTF8.self)
    print(str)
}catch{
    print(error)
}

options values:

  • .fragmentsAllowed: Specifies that the parser should allow top-level objects that aren’t arrays or dictionaries.
  • .prettyPrinted: Specifies that the output uses white space and indentation to make the resulting data more readable.
  • .sortedKeys: Specifies that the output sorts keys in lexicographic order.
  • .withoutEscapingSlashes: Specifies that the output doesn’t prefix slash characters with escape characters.