Hyperbee.Json 1.4.0-develop.240722203604

This is a prerelease version of Hyperbee.Json.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Hyperbee.Json --version 1.4.0-develop.240722203604                
NuGet\Install-Package Hyperbee.Json -Version 1.4.0-develop.240722203604                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Hyperbee.Json" Version="1.4.0-develop.240722203604" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Hyperbee.Json --version 1.4.0-develop.240722203604                
#r "nuget: Hyperbee.Json, 1.4.0-develop.240722203604"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Hyperbee.Json as a Cake Addin
#addin nuget:?package=Hyperbee.Json&version=1.4.0-develop.240722203604&prerelease

// Install Hyperbee.Json as a Cake Tool
#tool nuget:?package=Hyperbee.Json&version=1.4.0-develop.240722203604&prerelease                

Hyperbee.Json

Hyperbee.Json is a high-performance JSONPath parser for .NET, that supports both JsonElement and JsonNode.
The library is designed to be quick and extensible, allowing support for other JSON document types and functions.

Features

  • High Performance: Optimized for performance and efficiency.
  • Supports: JsonElement and JsonNode.
  • Extensible: Easily extended to support additional JSON document types and functions.
  • IEnumerable Results: Deferred execution queries with IEnumerable.
  • Conformant: Adheres to the JSONPath Specification RFC 9535.

JSONPath RFC

Hyperbee.Json conforms to the RFC, and aims to support the JSONPath consensus when the RFC is unopinionated. When the RFC is unopinionated, and where the consensus is ambiguous or not aligned with our performance and usability goals, we may deviate. Our goal is always to provide a robust and performant library while
strengthening our alignment with the RFC and the community.

Installation

Install via NuGet:

dotnet add package Hyperbee.Json

Usage

Basic Examples

Selecting Elements

var json = """
{ 
  "store": { 
    "book": [
      { "category": "fiction" }, 
      { "category": "science" } 
    ] 
  } 
}
""";

var root = JsonDocument.Parse(json);
var result = JsonPath.Select(root, "$.store.book[*].category");

foreach (var item in result)
{
    Console.WriteLine(item); // Output: "fiction" and "science"
}
Filtering

var json = """
{ 
  "store": { 
    "book": [
      { 
        "category": "fiction",
        "price": 10  
      }, 
      { 
        "category": "science",
        "price": 15  
      } 
    ] 
  } 
}
""";

var root = JsonDocument.Parse(json);
var result = JsonPath.Select(root, "$.store.book[?(@.price > 10)]");

foreach (var item in result)
{
    Console.WriteLine(item); // Output: { "category": "science", "price": 15 }
}
Working with (JsonElement, Path) pairs

var json = """
{ 
  "store": { 
    "book": [
      { "category": "fiction" }, 
      { "category": "science" } 
    ] 
  } 
}
""";

var root = JsonDocument.Parse(json);
var result = JsonPath.SelectPath(root, "$.store.book[0].category");

var (node, path) = result.First();

Console.WriteLine(node); // Output: "fiction"
Console.WriteLine(path); // Output: "$.store.book[0].category
Working with JsonNode

var json = """
{ 
  "store": { 
    "book": [
      { "category": "fiction" }, 
      { "category": "science" } 
    ] 
  } 
}
""";

var root = JsonNode.Parse(json);
var result = JsonPath.Select(root, "$.store.book[0].category");

Console.WriteLine(result.First()); // Output: "fiction"

JSONPath Syntax Overview

Here's a quick overview of JSONPath syntax:

JSONPath Description
$ Root node
@ Current node
.<name>, .'<name>', or ."<name>" Object member dot operator
[<name>], or ['<name>'], or ["<name>"] Object member subscript operator
[<index] Array access operator
[,] Union operator
[start:end:step] Array slice operator
*, or [*] Wildcard
.. Recursive descent
?<expr> Filter selector

JSONPath expressions refer to a JSON structure, and JSONPath assumes the name $ is assigned to the root JSON object.

JSONPath expressions can use dot-notation:

$.store.book[0].title

or bracket-notation:

$['store']['book'][0]['title']
  • JSONPath allows the wildcard symbol * for member names and array indices.
  • It borrows the descendant operator .. from [E4X][e4x]
  • It uses the @ symbol to refer to the current object.
  • It uses ? syntax for filtering.
  • It uses the array slice syntax proposal [start:end:step] from ECMASCRIPT 4.

Expressions can be used as an alternative to explicit names or indices, as in:

$.store.book[(length(@)-1)].title

Filter expressions are supported via the syntax ?(<boolean expr>), as in:

$.store.book[?(@.price < 10)].title

JSONPath Functions

JsonPath expressions support basic method calls.

Method Description Example
length() Returns the length of an array or string. $.store.book[?(length(@.title) > 5)]
count() Returns the count of matching elements. $.store.book[?(count(@.authors) > 1)]
match() Returns true if a string matches a regular expression. $.store.book[?(match(@.title,'.*Century.*'))]
search() Searches for a string within another string. $.store.book[?(search(@.title,'Sword'))]
value() Accesses the value of a key in the current object. $.store.book[?(value(@.price) < 10)]

JSONPath Extended Syntax

The library extends the JSONPath expression syntax to support additional features.

Operators Description Example
+ - * \ % Basic math operators. $[?(@.a + @.b == 3)]
in Tests is a value is in a set. $[?@.value in ['a', 'b', 'c'] ]

JSONPath Custom Functions

You can extend the supported function set by registering your own functions.

Example: Implement a JsonNode Path Function:

Step 1: Create a custom function that returns the path of a JsonNode.

public class PathNodeFunction() : ExtensionFunction( PathMethod, CompareConstraint.MustCompare )
{
    public const string Name = "path";
    private static readonly MethodInfo PathMethod = GetMethod<PathNodeFunction>( nameof( Path ) );

    private static ScalarValue<string> Path( IValueType argument )
    {
        return argument.TryGetNode<JsonNode>( out var node ) ? node?.GetPath() : null;
    }
}

Step 2: Register your custom function.

JsonTypeDescriptorRegistry.GetDescriptor<JsonNode>().Functions
    .Register( PathNodeFunction.Name, () => new PathNodeFunction() );

Step 3: Use your custom function in a JSONPath query.

var results = source.Select( "$..[?path(@) == '$.store.book[2].title']" );

Why Choose Hyperbee.Json ?

  • High Performance.
  • Supports both JsonElement, and JsonNode.
  • Deferred execution queries with IEnumerable.
  • Enhanced JsonPath syntax.
  • Extendable to support additional JSON document types.
  • RFC conforming JSONPath implementation.

Comparison with Other Libraries

There are excellent libraries available for RFC-9535 .NET JsonPath.

JsonPath.Net Json-Everything

  • Pros:

    • Comprehensive feature set.
    • Deferred execution queries with IEnumerable.
    • Enhanced JsonPath syntax.
    • Strong community support.
  • Cons:

    • No support for JsonElement.
    • More memory intensive.
    • Not quite as fast as other System.Text.Json implementations.

JsonCons.NET

  • Pros:

    • High performance.
    • Enhanced JsonPath syntax.
  • Cons:

    • No support for JsonNode.
    • Does not return an IEnumerable result (no defered query execution).

Json.NET Newtonsoft

  • Pros:

    • Comprehensive feature set.
    • Deferred execution queries with IEnumerable.
    • Documentation and examples.
    • Strong community support.
  • Cons:

    • No support for JsonElement, or JsonNode.

Benchmarks

Here is a performance comparison of various queries on the standard book store document.

{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}
 Method                           | Filter                           | Mean      | Error      | StdDev    | Allocated
--------------------------------- |--------------------------------- |-----------|------------|-----------|----------
 JsonPath_Hyperbee_JsonElement    | $..* `First()`                   |  3.105 us |  1.6501 us | 0.0904 us |   3.52 KB
 JsonPath_JsonEverything_JsonNode | $..* `First()`                   |  3.278 us |  3.3157 us | 0.1817 us |   3.53 KB
 JsonPath_Hyperbee_JsonNode       | $..* `First()`                   |  3.302 us |  3.2094 us | 0.1759 us |   3.09 KB
 JsonPath_JsonCons_JsonElement    | $..* `First()`                   |  6.170 us |  4.1597 us | 0.2280 us |   8.48 KB
 JsonPath_Newtonsoft_JObject      | $..* `First()`                   |  8.708 us |  8.7586 us | 0.4801 us |  14.22 KB
                                  |                                  |           |            |           |          
 JsonPath_JsonCons_JsonElement    | $..*                             |  5.792 us |  6.6920 us | 0.3668 us |   8.45 KB
 JsonPath_Hyperbee_JsonElement    | $..*                             |  7.504 us |  7.6479 us | 0.4192 us |   9.13 KB
 JsonPath_Hyperbee_JsonNode       | $..*                             | 10.320 us |  5.6676 us | 0.3107 us |  10.91 KB
 JsonPath_Newtonsoft_JObject      | $..*                             | 10.862 us |  0.4374 us | 0.0240 us |  14.86 KB
 JsonPath_JsonEverything_JsonNode | $..*                             | 21.914 us | 19.4680 us | 1.0671 us |  36.81 KB
                                  |                                  |           |            |           |          
 JsonPath_Hyperbee_JsonElement    | $..price                         |  4.557 us |  3.6801 us | 0.2017 us |    4.2 KB
 JsonPath_JsonCons_JsonElement    | $..price                         |  4.989 us |  2.3125 us | 0.1268 us |   5.65 KB
 JsonPath_Hyperbee_JsonNode       | $..price                         |  7.929 us |  0.6128 us | 0.0336 us |   7.48 KB
 JsonPath_Newtonsoft_JObject      | $..price                         | 10.511 us | 11.4901 us | 0.6298 us |   14.4 KB
 JsonPath_JsonEverything_JsonNode | $..price                         | 15.999 us |  0.5210 us | 0.0286 us |  27.63 KB
                                  |                                  |           |            |           |          
 JsonPath_Hyperbee_JsonElement    | $.store.book[?(@.price == 8.99)] |  4.221 us |  2.4758 us | 0.1357 us |   5.24 KB
 JsonPath_JsonCons_JsonElement    | $.store.book[?(@.price == 8.99)] |  5.424 us |  0.3551 us | 0.0195 us |   5.05 KB
 JsonPath_Hyperbee_JsonNode       | $.store.book[?(@.price == 8.99)] |  7.023 us |  7.0447 us | 0.3861 us |      8 KB
 JsonPath_Newtonsoft_JObject      | $.store.book[?(@.price == 8.99)] | 10.572 us |  2.4203 us | 0.1327 us |  15.84 KB
 JsonPath_JsonEverything_JsonNode | $.store.book[?(@.price == 8.99)] | 12.478 us |  0.5762 us | 0.0316 us |  15.85 KB
                                  |                                  |           |            |           |          
 JsonPath_Hyperbee_JsonElement    | $.store.book[0]                  |  2.720 us |  1.9771 us | 0.1084 us |   2.27 KB
 JsonPath_JsonCons_JsonElement    | $.store.book[0]                  |  3.266 us |  0.2087 us | 0.0114 us |   3.21 KB
 JsonPath_Hyperbee_JsonNode       | $.store.book[0]                  |  3.396 us |  0.5137 us | 0.0282 us |   2.77 KB
 JsonPath_JsonEverything_JsonNode | $.store.book[0]                  |  5.088 us |  0.1202 us | 0.0066 us |   5.96 KB
 JsonPath_Newtonsoft_JObject      | $.store.book[0]                  |  9.178 us |  9.5618 us | 0.5241 us |  14.56 KB

Additional Documentation

Additional documentation can be found in the project's /docs folder.

Credits

Hyperbee.Json is built upon the great work of several open-source projects. Special thanks to:

Contributing

We welcome contributions! Please see our Contributing Guide for more details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0 60 11/20/2024
3.0.0-develop.241120190203 29 11/20/2024
2.0.1 111 8/2/2024
2.0.0 90 8/1/2024
2.0.0-develop.240801174802 47 8/1/2024
1.4.0 127 7/22/2024
1.4.0-develop.240722203604 61 7/22/2024
1.3.0 105 7/12/2024
1.3.0-develop.240712213246 47 7/12/2024
1.2.1 116 7/2/2024
1.2.1-develop.240702141343 50 7/2/2024
1.2.1-develop.240625212527 53 6/25/2024
1.2.1-develop.240621185513 50 6/21/2024
1.2.1-develop.240620151810 54 6/20/2024
1.2.0-develop.240619213520 61 6/19/2024
1.1.0 122 6/14/2024
1.1.0-develop.240614155707 50 6/14/2024
1.0.0 125 4/8/2024