/JSONUtilities

Easily load JSON objects and decode them into structs or classes

Primary LanguageSwift

JSONUtilities

Build Status codecov.io

Easily load JSON objects and decode them into structs or classes. The JSONDecoder infers the type from the constant or variable definition to decode meaning no casting is needed.

  • Check out the JSONUtilitiesExample.playground for a working example

Installation

Either

OR

  • Add the files inside the JSONUtilities folder to your project

Types supported

JSON raw types:

  • Int
  • Double
  • Float
  • String
  • Bool

Array of JSON raw types:

  • [Int]
  • [Double]
  • [Float]
  • [String]
  • [Bool]

Custom JSON objects and custom JSON object arrays

e.g. if MyClass and MyStruct conform to Decodable protocol

  • MyClass
  • [MyClass]
  • MyStruct
  • [MyStruct]

Note: Raw dictionaries are intentionally not supported, i.e. [String : T]

Examples

Consider a JSON object that represents a person:

{
  "name" : "John Doe",
  "age" : 24,
  "weight" : 72.4
}

Decode JSON inline

let jsonDictionary = try JSONDictionary.fromFile("person.json")
let personDecoder = try JSONDecoder(jsonDictionary: jsonDictionary)
let name: String = try personDecoder.decode("name")
let age: Int = try personDecoder.decode("age")
let weight: Int = try personDecoder.decode("weight")
let profession: String? = personDecoder.decode("profession") // Optional decoding

Decode structs or classes

struct Person {

  let name : String
  let age : Int
  let weight : Double
  let profession : String?
   
  init(jsonDictionary: JSONDictionary) throws {
    let decoder = JSONDecoder(jsonDictionary: jsonDictionary)
    name = try decoder.decode("name")
    age = try decoder.decode("age")
    weight = try decoder.decode("weight")
    profession = decoder.decode("profession")
  }
  
}
class Person {

  let name : String
  let age : Int
  let weight : Double
  let profession : String?

  init(name: String,
    	  age: Int,
       weight: Double
       profession: String?) {
    self.name = name
    self.age = age
    self.weight = weight
    self.profession = profession
  }
  
  // Need a convenience initializer on a class because Swift does not allow to throw on a designated initializer
  convenience init(jsonDictionary: JSONDictionary) throws {
    let decoder = JSONDecoder(jsonDictionary: jsonDictionary)
    self.init(
      name : try decoder.decode("name"),
      age : try decoder.decode("age"),
      weight : try decoder.decode("weight"),
      profession : try decoder.decode("profession")
    )
  }
  
}

Decode nested structs or classes by conforming to the Decodable protocol

Consider a company JSON object:

{
    "name" : "Working name LTD.",
    "employees": [
        {
            "name": "John Doe",
            "age": 24,
            "weight": 72.4
        },
        {
            "name": "Jane Doe",
            "age": 22,
            "weight": 70.1
        }
    ]
}

The Company struct can decode an array of Person structs/classes by making Person conform to the Decodable protocol

struct Company {
  let name: String
  let employees: [Person]
  
  init(jsonDictionary: JSONDictionary) throws {
    let decoder = JSONDecoder(jsonDictionary: jsonDictionary)
    name = try decoder.decode("name")
    employees = try decoder.decode("employees")
  }
}