Hyperbee.Json 1.2.1-develop.240702141343

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.2.1-develop.240702141343                
NuGet\Install-Package Hyperbee.Json -Version 1.2.1-develop.240702141343                
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.2.1-develop.240702141343" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Hyperbee.Json --version 1.2.1-develop.240702141343                
#r "nuget: Hyperbee.Json, 1.2.1-develop.240702141343"                
#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.2.1-develop.240702141343&prerelease

// Install Hyperbee.Json as a Cake Tool
#tool nuget:?package=Hyperbee.Json&version=1.2.1-develop.240702141343&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 Consensus

Hyperbee.Json aims to follow the RFC and 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.

Installation

Install via NuGet:

dotnet add package Hyperbee.Json

Usage

Basic Examples

Selecting a Single Element
using Hyperbee.JsonPath;
using System.Text.Json;

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

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

Console.WriteLine(result.First()); // Output: "fiction"
Selecting Multiple Elements
using Hyperbee.JsonPath;
using System.Text.Json;

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
using Hyperbee.JsonPath;
using System.Text.Json;

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
using Hyperbee.JsonPath;
using System.Text.Json;

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
using Hyperbee.JsonPath;
using System.Text.Json.Nodes;

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 Reference

Here's a quick reference for 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 in the same way as XPath expressions are used in combination with an XML document. JSONPath assumes the name $ is assigned to the root level 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], and 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

using the symbol @ for the current object. Filter expressions are supported via the syntax ?(<boolean expr>), as in:

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

JSONPath Methods

JsonPath expressions support basic methods calls.

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

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

Example: JsonNode Path Function

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

public class PathNodeFunction() : FilterExtensionFunction( argumentCount: 1 )
{
    public const string Name = "path";
    private static readonly Expression PathExpression = Expression.Constant( (Func<IEnumerable<JsonNode>, string>) Path );

    protected override Expression GetExtensionExpression( Expression[] arguments )
    {
        return Expression.Invoke( PathExpression, arguments[0] );
    }

    public static string Path( IEnumerable<JsonNode> nodes )
    {
        var node = nodes.FirstOrDefault();
        return node?.GetPath();
    }
}

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']" );

Comparison with Other Libraries

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

JsonPath.Net Json-Everything

  • Pros:

    • Extensive JSON ecosystem.
    • Comprehensive feature set.
    • Deferred execution queries with IEnumerable.
    • Strong community support.
  • Cons:

    • No support for JsonElement.
    • 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.
    • Documentation and examples.
    • Strong community support.
    • Level 2 .NET Foundation Project.
  • Cons:

    • No support for JsonElement, or JsonNode.

Why Choose Hyperbee.Json ?

  • High Performance.

  • Supports both JsonElement, and JsonNode.

  • Deferred execution queries with IEnumerable.

  • Extendable to support additional JSON document types and functions.

  • Consensus focused JSONPath implementation.

  • 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 
|:----------------------- |:-------------------------------- |:--------- |:--------- |:--------- |:---------
| Hyperbee_JsonElement    | $..* `First()`                   |  3.026 us | 0.3647 us | 0.0200 us |   4.22 KB 
| JsonEverything_JsonNode | $..* `First()`                   |  3.170 us | 0.3034 us | 0.0166 us |   3.53 KB 
| Hyperbee_JsonNode       | $..* `First()`                   |  3.275 us | 1.7533 us | 0.0961 us |   3.37 KB 
| JsonCons_JsonElement    | $..* `First()`                   |  5.699 us | 0.2191 us | 0.0120 us |   8.48 KB 
| Newtonsoft_JObject      | $..* `First()`                   |  8.671 us | 1.7810 us | 0.0976 us |  14.22 KB 
|                         |                                  |           |           |           |           
| JsonCons_JsonElement    | $..*                             |  5.772 us | 3.8960 us | 0.2136 us |   8.45 KB 
| Hyperbee_JsonElement    | $..*                             |  8.179 us | 4.9380 us | 0.2707 us |  11.02 KB 
| Newtonsoft_JObject      | $..*                             |  9.867 us | 0.9006 us | 0.0494 us |  14.86 KB 
| Hyperbee_JsonNode       | $..*                             | 10.188 us | 2.0528 us | 0.1125 us |  10.83 KB 
| JsonEverything_JsonNode | $..*                             | 21.124 us | 5.1117 us | 0.2802 us |  36.81 KB 
|                         |                                  |           |           |           |           
| Hyperbee_JsonElement    | $..price                         |  4.867 us | 0.1883 us | 0.0103 us |   6.37 KB 
| JsonCons_JsonElement    | $..price                         |  4.924 us | 1.5997 us | 0.0877 us |   5.65 KB 
| Hyperbee_JsonNode       | $..price                         |  7.827 us | 5.0475 us | 0.2767 us |   8.77 KB 
| Newtonsoft_JObject      | $..price                         |  9.442 us | 1.0020 us | 0.0549 us |   14.4 KB 
| JsonEverything_JsonNode | $..price                         | 15.865 us | 2.1515 us | 0.1179 us |  27.63 KB 
|                         |                                  |           |           |           |           
| Hyperbee_JsonElement    | $.store.book[?(@.price == 8.99)] |  4.550 us | 1.0340 us | 0.0567 us |   9.08 KB 
| JsonCons_JsonElement    | $.store.book[?(@.price == 8.99)] |  5.341 us | 1.0738 us | 0.0589 us |   5.05 KB 
| Hyperbee_JsonNode       | $.store.book[?(@.price == 8.99)] |  7.341 us | 3.6147 us | 0.1981 us |  10.63 KB 
| Newtonsoft_JObject      | $.store.book[?(@.price == 8.99)] |  9.621 us | 5.1553 us | 0.2826 us |  15.84 KB 
| JsonEverything_JsonNode | $.store.book[?(@.price == 8.99)] | 11.789 us | 5.2457 us | 0.2875 us |  15.85 KB 
|                         |                                  |           |           |           |           
| Hyperbee_JsonElement    | $.store.book[0]                  |  2.896 us | 0.1069 us | 0.0059 us |   3.41 KB 
| JsonCons_JsonElement    | $.store.book[0]                  |  2.967 us | 0.1084 us | 0.0059 us |   3.21 KB 
| Hyperbee_JsonNode       | $.store.book[0]                  |  3.352 us | 0.1778 us | 0.0097 us |   3.58 KB 
| JsonEverything_JsonNode | $.store.book[0]                  |  4.779 us | 2.9031 us | 0.1591 us |   5.96 KB 
| Newtonsoft_JObject      | $.store.book[0]                  |  8.714 us | 2.5518 us | 0.1399 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.1 93 12/4/2024
3.0.0 85 11/20/2024
3.0.0-develop.241120190203 42 11/20/2024
2.0.1 125 8/2/2024
2.0.0 99 8/1/2024
2.0.0-develop.240801174802 52 8/1/2024
1.4.0 140 7/22/2024
1.4.0-develop.240722203604 66 7/22/2024
1.3.0 114 7/12/2024
1.3.0-develop.240712213246 52 7/12/2024
1.2.1 125 7/2/2024
1.2.1-develop.240702141343 55 7/2/2024
1.2.1-develop.240625212527 58 6/25/2024
1.2.1-develop.240621185513 57 6/21/2024
1.2.1-develop.240620151810 65 6/20/2024
1.2.0-develop.240619213520 68 6/19/2024
1.1.0 130 6/14/2024
1.1.0-develop.240614155707 53 6/14/2024
1.0.0 132 4/8/2024