mikhail-barg / jsonata.net.native

.Net native implementation of JSONata query and transformation language (http://jsonata.org)
MIT License
40 stars 6 forks source link
jsonata

About

.Net native implementation of JSONata query and transformation language.

This implementation is based on original jsonata-js source and also borrows some ideas from go port.

Performance

This implementation is about 100 times faster than straightforward wrapping of original jsonata.js with Jint JS Engine for C# (the wrapping is published as jsonata.net.js package).

For measurements code see src/BenchmarkApp in this repo.

Usage

Basic

Since version 2.0.0 this package does not depend on JSON.Net, instead it uses a custom implementation of JSON DOM and parser (see Jsonata.Net.Native.Json namespace). This change gave us the following benefits:

Still this custom implementation is modelled on Json.Net, so the following code should look familliar

using Jsonata.Net.Native;
using Jsonata.Net.Native.Json;
...
JToken data = JToken.Parse("{\"a\": \"b\"}");
...
JToken result = query.Eval(data);
Debug.Assert(result.ToFlatString() == "\"b\"");

JSON.Net

In case you work with JSON.Net you may use a separate binding package Jsonata.Net.Native.JsonNet and its single class JsonataExtensions to:

System.Text.Json

Same goes for when you use System.Text.Json. Separate binding package Jsonata.Net.Native.SystemTextJson provides similar JsonataExtensions class with similar wrappers for both JsonDocument/JsonElement (static DOM) and JsonNode (dynamic DOM).

Querying C# objects

It is also possible to create a JToken tree representation of existing C# object via Jsonata.Net.Native.Json.JToken.FromObject() and then query it with JSONata as a regular JSON. This may come in handy when you want to give your user some way to get and combine data from your program object model.

In case you want to go deeper and get more control over JSON representation of your objects, you may want to use Jsonata.Net.Native.JsonNet.JsonataExtensions.FromObjectViaNewtonsoft() and get all fancy stuff that Json.Net has to offer for this.

Since v2.2.0 there's also a (limited) support for converting JTokens back to C# objects via JToken.ToObject().

C# Features

We also provide an Exerciser app with same functionality as in original JSONata Exerciser: Exerciser

Parsing JSON with Jsonata.Net.Native.Json

As mentioned above, modern versions of Jsonata.Net.Native use custom implementation of JSON DOM and parsing. While re-implementation of JSON object model (JToken hierarchy) has been justified by performance and functionality reasons, writing just another JSON parser from scratch in 2022 looked a bit like re-inventing the wheel. On the other hand, forcing some specific external dependency just for the sake of parsing JSON looked even worse. So here you get just another JSON parser available via JToken.Parse() method.

This parser is being checked over the following test sets:

We have implemented a number of relaxations to "strict" parser spec used in test, like allowing trailing commas, or single-quoted strings. These options are configurable wia ParseSettings class. All relaxations are enabled by default.

When facing an invalid JSON, the parser would throw a JsonParseException

We have put some effort to this parser, but still the main purpose of the package is not parsing JSON by itself, so in case you need more sophisticated parsing features, like comments (or parsing 10 000 open braces) please use some mature parser package like Json.Net or System.Text.Json and convert results to Jsonata.Net.Native.Json.JToken via routines in a binding package.

Query DOM introspection and query creation via DOM

Since v2.7.0 we provide access to query DOM via Node classes in Jsonata.Net.Native.Dom namespace.

Currently it is possible to:

Please note that right now DOM API is experimental and subject to change in backwards-incompatible way without changing major release version of a library.

Some examples may be found here.

Rationale behind this API is here and here.

JSONata language features support

The goal of the project is to implement 100% of latest JSONata version (1.8.5 at the moment of writing these words), but it's still work in progress. Here's is a list of features in accordance to manual:

Also, need to check all TODO: markers in the code (TODO).

Detailed results for the reference test suite

We use the test suite from original JSONata JS implementation to check consistency and completeness of the port. Current test results for the latest test run are:

Full and brief test reports are also in the repo. Below are current states of each test group in the suite: