High performance JSONPath queries for Swift

Sextant

Sextant is a complete, high performance JSONPath implementation written in Swift. It was originally ported from SMJJSONPath, which in turn is a tight adaptation of the Jayway JsonPath implementation. Sextant has since been updated to bring it into compliance with other JSON path implementations (see issue), so this specific implementation now varies from the SMJJSONPath/Jayway implementation.

Overview

The original Stefan Goessner JsonPath implemenentation was released in 2007, and from it spawned dozens of different implementations. This JSONPath Comparison chart shows the wide array of available implemenations, and at the time of this writing a Swift implementation is not present (note that there exists the SwiftPath project, but it is not included in said chart due to critical errors when running on Linux.

Goals

  • Simple API
  • Full JSONPath implementation
  • High performance
  • Linux support

Usage

/// Each call to Sextant's query(values: ) will return an array on success and nil on failure
func testSimple0() {
    let json = #"["Hello","World"]"#
    guard let results = json.query(values: "$[0]") else { return XCTFail() }
    XCTAssertEqualAny(results[0], "Hello")
}

/// You can avoid the provided extensions and call query on the Sextant singleton directly
func testSimple1() {
    let json = #"["Hello","World"]"#
    guard let jsonData = json.data(using: .utf8) else { return }
    guard let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: []) else { return }
    guard let results = Sextant.shared.query(jsonObject, values: "$[0]") else { return XCTFail() }
    XCTAssertEqualAny(results[0], "Hello")
}

/// Works with any existing JSON-like structure
func testSimple2() {
    let data = [ "Hello", "World" ]
    guard let results = data.query(values: "$[0]") else { return XCTFail() }
    XCTAssertEqualAny(results[0], "Hello")
}

/// Automatically covert to simple tuples
func testSimple3() {
    let json = #"{"name":"Rocco","age":42}"#
    
    guard let person: (name: String?, age: Int?) = json.query("$.['name','age']") else { return XCTFail() }
    XCTAssertEqual(person.name, "Rocco")
    XCTAssertEqual(person.age, 42)
}

/// Supports Decodable structs
func testSimple4() {
    let json = #"{"data":{"people":[{"name":"Rocco","age":42},{"name":"John","age":12},{"name":"Elizabeth","age":35},{"name":"Victoria","age":85}]}}"#
    
    class Person: Decodable {
        let name: String
        let age: Int
    }
    
    guard let persons: [Person] = json.query("$..[?(@.name)]") else { return XCTFail() }
    XCTAssertEqual(persons[0].name, "Rocco")
    XCTAssertEqual(persons[0].age, 42)
    XCTAssertEqual(persons[2].name, "Elizabeth")
    XCTAssertEqual(persons[2].age, 35)
}

/// Easily combine results from multiple queries
func testSimple5() {
    let json1 = #"{"error":"Error format 1"}"#
    let json2 = #"{"errors":[{"title:":"Error!","detail":"Error format 2"}]}"#
            
    let queries: [String] = [
        "$.error",
        "$.errors[0].detail",
    ]
    
    XCTAssertEqualAny(json1.query(string: queries), "Error format 1")
    XCTAssertEqualAny(json2.query(string: queries), "Error format 2")
}

Installation

Sextant is fully compatible with the Swift Package Manager

dependencies: [
    .package(url: "https://github.com/KittyMac/Sextant.git", .branch("main"))
],

License

Sextant is free software distributed under the terms of the MIT license, reproduced below. Sextant may be used for any purpose, including commercial purposes, at absolutely no cost. No paperwork, no royalties, no GNU-like “copyleft” restrictions. Just download and enjoy.

Copyright (c) 2021 Chimera Software, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

GitHub

View Github