Skip to content

A simple Swift library for working with generic JSON structures

License

Notifications You must be signed in to change notification settings

CarlEkman/CodingKit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

91 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Generic JSON

Build Status

Generic JSON makes it easy to deal with freeform JSON strings without creating a separate, well-typed structure.

Codable and freeform JSON

Swift 4 introduced a new JSON encoding and decoding machinery represented by the Codable protocol. The feature is very nice and very type-safe, meaning it’s no longer possible to just willy-nilly decode a JSON string pulling random untyped data from it. Which is good™ most of the time – but what should you do when you do want to just willy-nilly encode or decode a JSON string without introducing a separate, well-typed structure for it? For example:

// error: heterogeneous collection literal could only be inferred to '[String : Any]';
// add explicit type annotation if this is intentional
let json = [
    "foo": "foo",
    "bar": 1,
]

// Okay then:
let json: [String:Any] = [
    "foo": "foo",
    "bar": 1,
]

// But: fatal error: Dictionary<String, Any> does not conform to Encodable because Any does not conform to Encodable.
let encoded = try JSONEncoder().encode(json)

So this doesn’t work very well. Also, the json value can’t be checked for equality with another, although arbitrary JSON values should support equality. Enter JSON.

Usage

Create a JSON structure

let json: JSON = [
    "foo": "foo",
    "bar": 1,
]

// "{"bar":1,"foo":"foo"}"
let str = try String(data: try JSONEncoder().encode(json), encoding: .utf8)!
let hopefullyTrue = (json == json) // true!

Convert Encodable objects into a generic JSON structure

struct Player: Codable {
    let name: String
    let swings: Bool
}

let val = try JSON(encodable: Player(name: "Miles", swings: true))
val == [
    "name": "Miles",
    "swings": true,
] // true

Query Values

Consider the following JSON structure:

let json: JSON = [
    "num": 1,
    "str": "baz",
    "bool": true,
    "obj": [
        "foo": "jar",
        "bar": 1,
    ]
]

Querying values can be done using optional property accessors, subscripting or dynamic member subscripting:

// Property accessors
if let str = json.objectValue?["str"]?.stringValue {  }
if let foo = json.objectValue?["obj"]?.objectValue?["foo"]?.stringValue {  }

// Subscripting
if let str = json["str"]?.stringValue {  }
if let foo = json["obj"]?["foo"]?.stringValue {  }

// Dynamic member subscripting
if let str = json.str?.stringValue {  }
if let foo = json.obj?.foo?.stringValue {  }

You may even drill through nested structures using a dot-separated key path:

let val = json[keyPath: "obj.foo"] // "jar"

About

A simple Swift library for working with generic JSON structures

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 98.3%
  • Objective-C 1.7%