Low level JSON API (idea)

SwiftFoundationEssentials contains JSON parsing/generating for JSON Codable encoder/decoder. There are situations where one would like to have a finer control over JSON. Original Foundation has JSONSerialization, however it uses older Objective C NS* types.

Example Case: An application document format that might be produced or consumed by third-parties and its version might change (to a reasonable degree). The application opens/imports older, or even newer versions of a document, or document from a third party. The document consumption process must be flexible enough to accept potentially differently shaped structure. That might require different decoding strategies based on a top-level structure

Having an API to inspect and ad-hoc parse/generate JSON would allow:

  • separate parsing code from the objects being encoded into various version-specific decoders
  • have better control over how the lowest level objects are encoded/decoded
  • better error reporting (not obscured by type recursion, with added application-specific domain knowledge), or even ability to collect multiple errors at once

Codable protocol seems to me to be more suited for immediate consumption rather than long term storage or foreign interfaces. One can use userInfo, however the whole encoding/decoding process is obscured by being scattered all around the types. In addition to that, it might require custom "decoded alternative" types to be created just for the purpose of foreign format decoding before them being converted to proper document types.

The following (or analogous) API would cover quite a lot of use cases for custom JSON inspection and parsing:

// Might be either a protocol or a concrete type
protocol JSONValue {
    func asDictionary() -> [String:JSONValue]?
    func asArray() -> [String:JSONValue]?
    func asString() -> String?
    func asInt() -> Int?
    func asDouble() -> Double?
    func asBool() -> Bool?
    var isNull: Bool
    var type: JSONType

    // Nice to have
    func value(atPath: [JSONKey]) -> JSONValue?
}

public enum JSONType: Equatable {
    case int
    case double
    case string
    case bool
    case array
    case object
    case null
}

public struct JSONKey {...}

(The above code is rather a conversation starter.)

What do you think about the possibility and feasibility of exposing some of the lower level functionality for reading/writing a JSON? Especially the reading part:

  1. having a set of JSON functions and/or immutable types on top of already parsed data
  2. Allow the user to perform explicit and transparent transformation from JSON to custom types by providing direct access to the whole JSON structure.

Thoughts?

2 Likes

This would be amazing! As you’ve already pointed out, JSONSerialization is not Swifty at all (even on macOS I don’t like working with it). The simple value-type based API you sketched out would already go a long way. Especially with the value(atPath:) method!

Have you looked into IkigaJSON?