Hyperbee.Json
1.3.0-develop.240712213246
See the version list below for details.
dotnet add package Hyperbee.Json --version 1.3.0-develop.240712213246
NuGet\Install-Package Hyperbee.Json -Version 1.3.0-develop.240712213246
<PackageReference Include="Hyperbee.Json" Version="1.3.0-develop.240712213246" />
paket add Hyperbee.Json --version 1.3.0-develop.240712213246
#r "nuget: Hyperbee.Json, 1.3.0-develop.240712213246"
// Install Hyperbee.Json as a Cake Addin #addin nuget:?package=Hyperbee.Json&version=1.3.0-develop.240712213246&prerelease // Install Hyperbee.Json as a Cake Tool #tool nuget:?package=Hyperbee.Json&version=1.3.0-develop.240712213246&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 the
?()
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 methods 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 Custom Functions
You can also 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() : FilterExtensionFunction( PathMethodInfo, FilterExtensionInfo.MustCompare )
{
public const string Name = "path";
private static readonly MethodInfo PathMethodInfo = GetMethod<PathNodeFunction>( nameof( Path ) );
private static INodeType Path( INodeType arg )
{
if ( arg is not NodesType<JsonNode> nodes )
return Constants.Null;
var node = nodes.FirstOrDefault();
return new ValueType<string>( 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:
- Comprehensive feature set.
- Deferred execution queries with
IEnumerable
. - Strong community support.
- .NET Foundation Project.
Cons:
- No support for
JsonElement
. - 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.
- Documentation and examples.
- Strong community support.
- .NET Foundation Project.
Cons:
- No support for
JsonElement
, orJsonNode
.
- No support for
Why Choose Hyperbee.Json ?
- High Performance.
- Supports both
JsonElement
, andJsonNode
. - Deferred execution queries with
IEnumerable
. - Extendable to support additional JSON document types and functions.
- RFC conforming 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.186 us | 0.6615 us | 0.0363 us | 4.3 KB
| Hyperbee_JsonNode | $..* `First()` | 3.521 us | 0.1192 us | 0.0065 us | 3.45 KB
| JsonEverything_JsonNode | $..* `First()` | 3.545 us | 0.7400 us | 0.0406 us | 3.53 KB
| JsonCons_JsonElement | $..* `First()` | 5.793 us | 1.3811 us | 0.0757 us | 8.48 KB
| Newtonsoft_JObject | $..* `First()` | 9.119 us | 5.3278 us | 0.2920 us | 14.22 KB
| | | | | |
| JsonCons_JsonElement | $..* | 6.098 us | 2.0947 us | 0.1148 us | 8.45 KB
| Hyperbee_JsonElement | $..* | 8.812 us | 1.6812 us | 0.0922 us | 11.1 KB
| Hyperbee_JsonNode | $..* | 10.621 us | 1.2452 us | 0.0683 us | 10.91 KB
| Newtonsoft_JObject | $..* | 11.037 us | 5.4690 us | 0.2998 us | 14.86 KB
| JsonEverything_JsonNode | $..* | 23.329 us | 2.2255 us | 0.1220 us | 36.81 KB
| | | | | |
| Hyperbee_JsonElement | $..price | 5.248 us | 3.4306 us | 0.1880 us | 6.45 KB
| JsonCons_JsonElement | $..price | 5.402 us | 0.3285 us | 0.0180 us | 5.65 KB
| Hyperbee_JsonNode | $..price | 8.483 us | 2.0999 us | 0.1151 us | 8.86 KB
| Newtonsoft_JObject | $..price | 10.109 us | 9.6403 us | 0.5284 us | 14.4 KB
| JsonEverything_JsonNode | $..price | 17.054 us | 10.5303 us | 0.5772 us | 27.63 KB
| | | | | |
| Hyperbee_JsonElement | $.store.book[?(@.price == 8.99)] | 4.486 us | 3.2931 us | 0.1805 us | 5.82 KB
| JsonCons_JsonElement | $.store.book[?(@.price == 8.99)] | 5.381 us | 3.3826 us | 0.1854 us | 5.05 KB
| Hyperbee_JsonNode | $.store.book[?(@.price == 8.99)] | 7.354 us | 4.9887 us | 0.2734 us | 8.47 KB
| Newtonsoft_JObject | $.store.book[?(@.price == 8.99)] | 10.519 us | 3.5514 us | 0.1947 us | 15.84 KB
| JsonEverything_JsonNode | $.store.book[?(@.price == 8.99)] | 11.912 us | 7.6346 us | 0.4185 us | 15.85 KB
| | | | | |
| Hyperbee_JsonElement | $.store.book[0] | 2.722 us | 0.5813 us | 0.0319 us | 2.27 KB
| JsonCons_JsonElement | $.store.book[0] | 3.150 us | 1.7316 us | 0.0949 us | 3.21 KB
| Hyperbee_JsonNode | $.store.book[0] | 3.339 us | 0.1733 us | 0.0095 us | 2.77 KB
| JsonEverything_JsonNode | $.store.book[0] | 4.974 us | 3.2013 us | 0.1755 us | 5.96 KB
| Newtonsoft_JObject | $.store.book[0] | 9.482 us | 7.0303 us | 0.3854 us | 14.56 KB
Additioal 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 | 58 | 11/20/2024 |
3.0.0-develop.241120190203 | 27 | 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 |