Hyperbee.Json
1.4.0-develop.240722203604
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
<PackageReference Include="Hyperbee.Json" Version="1.4.0-develop.240722203604" />
paket add Hyperbee.Json --version 1.4.0-develop.240722203604
#r "nuget: Hyperbee.Json, 1.4.0-develop.240722203604"
// 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
andJsonNode
. - Extensible: Easily extended to support additional JSON document types and functions.
IEnumerable
Results: Deferred execution queries withIEnumerable
.- 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
, andJsonNode
. - 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.
- No support for
JsonCons.NET
Pros:
- High performance.
- Enhanced JsonPath syntax.
Cons:
- No support for
JsonNode
. - Does not return an
IEnumerable
result (no defered query execution).
- No support for
Json.NET Newtonsoft
Pros:
- Comprehensive feature set.
- Deferred execution queries with
IEnumerable
. - Documentation and examples.
- Strong community support.
Cons:
- No support for
JsonElement
, orJsonNode
.
- No support for
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:
- System.Text.Json team for their work on the
System.Text.Json
library. - Stefan Goessner for the original JSONPath implementation.
- Atif Aziz's C# port of Goessner's JSONPath library .NET JSONPath.
- Christoph Burgmer JSONPath consensus effort.
- JSONPath Compliance Test Suite Team.
Contributing
We welcome contributions! Please see our Contributing Guide for more details.
Product | Versions 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. |
-
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 |