Crate rsonpath

source ·
Expand description

Blazing fast execution of JSONPath queries.

JSONPath parser, execution engines and byte stream utilities useful when parsing JSON structures.

Examples

use rsonpath::engine::{Compiler, Engine, RsonpathEngine};
use rsonpath::input::OwnedBytes;
use rsonpath::query::JsonPathQuery;
use rsonpath::result::count::CountRecorder;

// Parse a JSONPath query from string.
let query = JsonPathQuery::parse("$..phoneNumbers[*].number")?;
// Convert the contents to the Input type required by the Engines.
// Currently requires the contents to be owned and allocations to occur,
// this is a known limitation tracked as issue #23
// (https://github.com/V0ldek/rsonpath/issues/23).
let mut contents = r#"
{
  "person": {
    "name": "John",
    "surname": "Doe",
    "phoneNumbers": [
      {
        "type": "Home",
        "number": "111-222-333"
      },
      {
        "type": "Work",
        "number": "123-456-789"
      }
    ]
  }
}
"#.to_owned();
let input = OwnedBytes::try_from(contents).unwrap();
// Compile the query. The engine can be reused to run the same query on different contents.
let engine = RsonpathEngine::compile_query(&query)?;
// Count the number of occurrences of elements satisfying the query.
let count = engine.count(&input)?;

assert_eq!(2, count);

Input JSON assumptions

The JSON must be a syntactically valid JSON encoded in UTF-8 as defined by RFC4627.

If the assumptions are violated the algorithm’s behavior is undefined. It might return nonsensical results, not process the whole document, or stop with an error. It should not panic – if you encounter a panic, you may report it as a bug. Some simple mistakes are caught, for example missing closing brackets or braces, but robust validation is sacrificed for performance. Asserting the assumptions falls on the user of this library. If you need a high-throughput parser that validates the document, take a look at simdjson.

JSONPath language

The library implements the JSONPath syntax as established by Stefan Goessner in https://goessner.net/articles/JsonPath/. That implementation does not describe its semantics. There is no guarantee that this library has the same semantics as Goessner’s implementation. The semantics used by rsonpath are described below.

Grammar

query = [root] , { selector }
root = "$"
selector = child | descendant | wildcard child | wildcard descendant
wildcard child = ".*" | "[*]"
wildcard descendant = "..*" | "..[*]"
child = dot | index
dot = "." , member
descendant = ".." , ( member | index )
index = "[" , quoted member , "]"
member = member first , { member character }
member first = ALPHA | "_" | NONASCII
member character = ALPHANUMERIC | "_" | NONASCII
quoted member = ("'" , single quoted member , "'") | ('"' , double quoted member , '"')
single quoted member = { UNESCAPED | ESCAPED | '"' | "\'" }
double quoted member = { UNESCAPED | ESCAPED | "'" | '\"' }

ALPHA = ? [A-Za-z] ?
ALPHANUMERIC = ? [A-Za-z0-9] ?
NONASCII = ? [\u0080-\u10FFFF] ?
UNESCAPED = ? [^'"\u0000-\u001F] ?
ESCAPED = ? \\[btnfr/\\] ?

Semantics

The query is executed from left to right, selector by selector. When a value is found that matches the current selector, the execution advances to the next selector and evaluates it recursively within the context of that value.

Root selector ($)

The root selector may only appear at the beginning of the query and is implicit if not specified. It matches the root object or array. Thus the query “$” gives either 1 or 0 results, if the JSON is empty or non-empty, respectively.

Child selector (.<member>, [<member>])

Matches any value under a specified key in the current object and then executes the rest of the query on that value.

Child wildcard selector (.*, [*])

Matches any value regardless of key in the current object, or any value within the current array, and then executes the rest of the query on that value.

Descendant selector (..<member>, ..[<member>])

Switches the engine into a recursive descent mode. Looks for the specified key in every value nested in the current object or array, recursively, and then executes the rest of the query on that value..

Descendant wildcard selector (..*, ..[*])

Switches the engine into a recursive descent mode. Matches any value regardless of key in any object, or any value within any array nested within the current object or array, recursively, and then executes the rest of the query on that value.

Active development

Only the aforementioned selectors are supported at this moment. This library is under active development.

Modules

  • Classifiers working on the input stream.
  • Base traits for different implementations of JSONPath execution engines.
  • Common errors shared across the library.
  • Input structures that can be fed into an Engine.
  • Defines JSONPath query structure and parsing logic.
  • Result types that can be returned by a JSONPath query engine.

Traits