JSON

@dynamicMemberLookup
public enum JSON : Hashable, CustomStringConvertible

A representation of ambigious JSON.

Heterogeneous Arrays.

Take for exmaple the JSON below:

{
    "users": [
        {
            "age": 18,
            "name": {
                "first": "Caleb",
                "last": "Kleveter"
            }
        }
    ],
    "metadata": [42, 3.14, true, "fizz buzz"]
}

The users data is pretty normal, but the metadata array can’t be represented by standard arrays.

The metadata array, when decoded to a JSON instance, will result in this case:

JSON.array([.number(.int(42)), .number(.double(3.14)), .bool(true), .string("fizz buzz")])

Value Unwrapping

Getting the associated value from an enum case can be a real pain, so there are properties for each case to unwrap the value.

If you have the example JSON above, it is an .object case. You can use the .object property to get the [String: JSON] value it wraps:

json.object // [String: JSON]?

There are also properties for .null, .string, .bool, .int, .float, .double, and .array. Be sure to read the docs for the .null property.

These properties also have setters. They let you set the value of the current JSON case. They will set the case regardless the current type, so if the case is a .bool, you can use .string and the case will be changed to a .string case.

var json = JSON.bool(true)
json.string = "Fizz Buzz"
print(json) // "\"Fizz Buzz\""

Dynamic Access

JSON supports @dynamicMemberLookup, so it is really easy to access values your JSON objects/arrays:

let firstname = json.users.0.name.first.string

This also works for setting JSON values:

json.users.0.name.first = "Tanner"
  • Gets the value of a .null case.

    You will always get nil from this property. This is because the JSON case is itself .null, or it isn’t so conversion failed and you get nil.

    The Wrapped type is Never so the compiler can gurantee that the value is nil.

    Declaration

    Swift

    public var null: Optional<Never> { get set }
  • Accesses the value of a .bool case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var bool: Bool? { get set }
  • Accesses the value of a .string case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var string: String? { get set }
  • int

    Accesses the value of a Number.int case wrapped in a .number case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var int: Int? { get set }
  • Accesses the value of a Number.float case wrapped in a .number case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var float: Float? { get set }
  • Accesses the value of a Number.double case wrapped in a .number case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var double: Double? { get set }
  • Accesses the value of a Number.decimal case wrapped in a .number case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var decimal: Decimal? { get set }
  • Accesses the value of an .array case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var array: [JSON]? { get set }
  • Accesses the value of an .object case.

    The setter will set the JSON case regardles the current type.

    Declaration

    Swift

    public var object: [String : JSON]? { get set }
  • Converts a non-optiona JSON case to an optional JSON case.

    If the JSON case is .null, then nil will be returned. Otherwise the JSON case is returned. This allows you to unwrap a case to make sure it isn’t null:

    if let value = json.optional {
        // ...
    }
    

    Declaration

    Swift

    public var optional: Optional<JSON> { get }
  • A null JSON value.

    This represents an explicit null value in the JSON. A non-existant key or index has no representation.

    {
        "foo": null
    }
    

    Declaration

    Swift

    case null
  • A boolean JSON value.

    {
        "fizz": true,
        "buzz": false
    }
    

    Declaration

    Swift

    case bool(Bool)
  • A string JSON value.

    {
        "foo": "bar"
    }
    

    Declaration

    Swift

    case string(String)
  • A number JSON value.

    This case wraps a Number enum case, which will be an int, float, or double.

    {
        "answer": 42,
        "pi": 3.1415
    }
    

    Declaration

    Swift

    case number(Number)
  • A JSON array of values.

    [
        "foo",
        "bar",
        1997,
    ]
    

    Declaration

    Swift

    case array([JSON])
  • A JSON object which maps string keys to JSON values.

    {
        "foo: "bar",
        "fizz": true,
        "bar": [98, 97, 114]
    }
    

    Declaration

    Swift

    case object([String : JSON])
  • Creates a JSON instance with the .null case.

    Declaration

    Swift

    public init()
  • Creates a JSON instance with the .string case.

    Declaration

    Swift

    public init(_ string: String)

    Parameters

    string

    The String held by the .string case.

  • Creates a JSON instance with the .bool case.

    Declaration

    Swift

    public init(_ bool: Bool)

    Parameters

    bool

    The Bool held by the .bool case.

  • Creates a JSON instance with the .number(Number.int) case.

    Declaration

    Swift

    public init(_ int: Int)

    Parameters

    int

    The Int held by the .int case.

  • Creates a JSON instance with the .number(Number.float) case.

    Declaration

    Swift

    public init(_ float: Float)

    Parameters

    float

    The Float held by the .float case.

  • Creates a JSON instance with the .number(Number.double) case.

    Declaration

    Swift

    public init(_ double: Double)

    Parameters

    double

    The Double held by the .double case.

  • Creates a JSON instance with the .number(Number.decimal) case.

    Declaration

    Swift

    public init(_ decimal: Decimal)

    Parameters

    decimal

    The Decimal held by the .decimal case.

  • Creates a JSON instance with the .array case.

    Declaration

    Swift

    public init(_ array: [JSON])

    Parameters

    array

    The JSON values held by the .array case.

  • Creates a JSON instance with the .object case.

    Declaration

    Swift

    public init(_ object: [String : JSON])

    Parameters

    array

    The JSON key/values map held by the .object case.

  • Creates a JSON instance with the .number case.

    Declaration

    Swift

    public init<I>(_ fwi: I) where I : FixedWidthInteger

    Parameters

    fwi

    A fixed-width integer which is converted to an Int and then passed into a .number(.int) case.

  • Creates a JSON instance from raw JSON data.

    Declaration

    Swift

    public init(data: Data) throws

    Parameters

    data

    The JSON data to decode to JSON.

  • Gets the JSON value for a given key.

    Complexity

    O(n), where n is the number of elements in the JSON array you are accessing object values from. More often though, you are accessing object values via key, and that is O(1).

    Most of the time, the member passed in with be a String key. This will get a value for an object key:

    json.user.first_name // .string("Tanner")
    

    However, Int members are also supported in that case of a JSON array:

    json.users.0.age // .number(.int(42))
    

    Declaration

    Swift

    public subscript(dynamicMember member: String) -> JSON { get set }

    Parameters

    member

    The key for JSON objects or index for JSON arrays of the value to get.

    Return Value

    The JSON value for the given key or index. .null is returned if the value is not found or the JSON value this subscript is called on does not have nested data, i.e. .string, .bool, etc.

  • Accesses the JSON value at a given key/index path.

    Complexity

    O(n) where n is the number of elements in the path.

    To get the value, .get(_:) is used. To set the value, .set(_:to:) is used.

    Declaration

    Swift

    public subscript(path: String...) -> JSON { get set }

    Parameters

    path

    The key/index path to access.

    Return Value

    Thw JSON value(s) found at the path passed in.

  • Gets the JSON at a given path.

    Complexity

    O(n) where n is the number of elements in the path.

    If an .array case is found, the path key will be converted to an index and the array element at that index will be returned. If key to index conversion fails, or the index it outside the range of the array, .null is returned.

    Declaration

    Swift

    public func get(_ path: [String]) -> JSON

    Parameters

    path

    The keys and indexes to the desired JSON value(s).

    Return Value

    Thw JSON value(s) found at the path passed in. You will get a .null case if no JSON is found at the given path.

  • Sets the value of an object key or array index.

    Complexity

    O(n), where n is the number of elements in the path. This method is recursive, so you may have adverse performance for long paths.

    Declaration

    Swift

    public mutating func set<Path>(_ path: Path, to json: JSON) where Path : Collection, Path.Element == String

    Parameters

    path

    The path of the value to set.

    json

    The JSON value to set the index or key to.

  • Removes a key/value pair from an object at a given path.

    The JSON type converts nil to it’s .null case, so if you try to remove a value like this:

    json["foo", "bar"] = nil
    

    You just set the object’s property to null:

    {
        "foo": {
            "bar": null
        }
    }
    

    To actually remove a property from an object, you use .remove(_:) with the path to the property to remove:

    json.remove(["foo", "bar"])
    

    Will result in this json structure:

    {
        "foo": {}
    }
    

    Complexity

    O(n), where n is the number of elements in the path to remove. Keep in mind that this method is recursive, so each succesive eleemnt in the path will add another call to the stack.

    Declaration

    Swift

    public mutating func remove<Path>(_ path: Path) where Path : Collection, Path.Element == String

    Parameters

    path

    The key path to the json property to remove.

  • See CustomStringConvertible.description.

    This textal representation is compressed, so you might need to prettify it to read it.

    Declaration

    Swift

    public var description: String { get }
  • Indicates whether this case is a .null.

    Declaration

    Swift

    public var isNull: Bool { get }
  • Indicates whether this case is a .bool.

    Declaration

    Swift

    public var isBool: Bool { get }
  • Indicates whether this case is a .string.

    Declaration

    Swift

    public var isString: Bool { get }
  • Indicates whether this case is a .number.

    Declaration

    Swift

    public var isNumber: Bool { get }
  • Indicates whether this case is a .number(.int).

    Declaration

    Swift

    public var isInt: Bool { get }
  • Indicates whether this case is a .number(.float).

    Declaration

    Swift

    public var isFloat: Bool { get }
  • Indicates whether this case is a .number(.double).

    Declaration

    Swift

    public var isDouble: Bool { get }
  • Indicates whether the case is a.object.

    Declaration

    Swift

    public var isObject: Bool { get }
  • Indicates whether the case is an.array.

    Declaration

    Swift

    public var isArray: Bool { get }
  • See Decodable.init(from:).

    Declaration

    Swift

    public init(from decoder: Decoder) throws
  • See Encodable.encode(to:).

    Declaration

    Swift

    public func encode(to encoder: Encoder) throws
  • A generic CodingKey type that supports any value.

    See more

    Declaration

    Swift

    public struct CodingKeys : CodingKey
  • Creates a JSON instance with the .null case.

    Declaration

    Swift

    public init(nilLiteral: ())
  • Creates a JSON instance with the .string case.

    Declaration

    Swift

    public init(stringLiteral value: String)

    Parameters

    value

    The String wrapped by the .string case.

  • Creates a JSON instance with the .number(Number.int) case.

    Declaration

    Swift

    public init(integerLiteral value: Int)

    Parameters

    value

    The Int wrapped by the .int case.

  • Creates a JSON instance with the .number(Number.double) case.

    Declaration

    Swift

    public init(floatLiteral value: Double)

    Parameters

    value

    The Double wrapped by the .double case.

  • Creates a JSON instance with the .bool case.

    Declaration

    Swift

    public init(booleanLiteral value: Bool)

    Parameters

    value

    The Bool wrapped by the .bool case.

  • Creates a JSON instance with the .array case.

    Declaration

    Swift

    public init(arrayLiteral elements: SafeJSONRepresentable...)

    Parameters

    elements

    The array elements, which will be converted to their JSON representation, wrapped by the .array case.

  • Creates a JSON instance with the .array case.

    Declaration

    Swift

    public init(dictionaryLiteral elements: (String, SafeJSONRepresentable)...)

    Parameters

    elements

    The dictionary key/value pairs wrapped in the .object case, with the values converted to their JSON representations.