-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
118 changed files
with
11,284 additions
and
9,252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,7 +160,7 @@ or bracket-notation: | |
- 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 `?` 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: | ||
|
@@ -173,38 +173,46 @@ Filter expressions are supported via the syntax `?(<boolean expr>)`, as in: | |
|
||
### JSONPath Functions | ||
|
||
JsonPath expressions support basic methods calls. | ||
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)]` | ||
| `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. | `$[[email protected] in ['a', 'b', 'c'] ]` | ||
|
||
|
||
### JSONPath Custom Functions | ||
|
||
You can also extend the supported function set by registering your own functions. | ||
You can extend the supported function set by registering your own functions. | ||
|
||
**Example:** Implement a `JsonNode` Path Function: | ||
|
||
**Example:** Implement a `JsonNode` Path Function: | ||
|
||
**Step 1:** Create a custom function that returns the path of a `JsonNode`. | ||
|
||
```csharp | ||
public class PathNodeFunction() : FilterExtensionFunction( PathMethodInfo, FilterExtensionInfo.MustCompare ) | ||
public class PathNodeFunction() : ExtensionFunction( PathMethod, CompareConstraint.MustCompare ) | ||
{ | ||
public const string Name = "path"; | ||
private static readonly MethodInfo PathMethodInfo = GetMethod<PathNodeFunction>( nameof( Path ) ); | ||
private static readonly MethodInfo PathMethod = GetMethod<PathNodeFunction>( nameof( Path ) ); | ||
|
||
private static INodeType Path( INodeType arg ) | ||
private static ScalarValue<string> Path( IValueType argument ) | ||
{ | ||
if ( arg is not NodesType<JsonNode> nodes ) | ||
return Constants.Null; | ||
|
||
var node = nodes.FirstOrDefault(); | ||
return new ValueType<string>( node?.GetPath() ); | ||
return argument.TryGetNode<JsonNode>( out var node ) ? node?.GetPath() : null; | ||
} | ||
} | ||
``` | ||
|
||
|
@@ -221,6 +229,15 @@ JsonTypeDescriptorRegistry.GetDescriptor<JsonNode>().Functions | |
var results = source.Select( "$..[?path(@) == '$.store.book[2].title']" ); | ||
``` | ||
|
||
## Why Choose [Hyperbee.Json](https://github.com/Stillpoint-Software/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. | ||
|
@@ -230,11 +247,12 @@ There are excellent libraries available for RFC-9535 .NET JsonPath. | |
- **Pros:** | ||
- Comprehensive feature set. | ||
- Deferred execution queries with `IEnumerable`. | ||
- Enhanced JsonPath syntax. | ||
- Strong community support. | ||
- .NET Foundation Project. | ||
|
||
- **Cons:** | ||
- No support for `JsonElement`. | ||
- More memory intensive. | ||
- Not quite as fast as other `System.Text.Json` implementations. | ||
|
||
### [JsonCons.NET](https://danielaparker.github.io/JsonCons.Net/articles/JsonPath/JsonConsJsonPath.html) | ||
|
@@ -251,21 +269,13 @@ There are excellent libraries available for RFC-9535 .NET JsonPath. | |
|
||
- **Pros:** | ||
- Comprehensive feature set. | ||
- Deferred execution queries with `IEnumerable`. | ||
- Documentation and examples. | ||
- Strong community support. | ||
- .NET Foundation Project. | ||
|
||
- **Cons:** | ||
- No support for `JsonElement`, or `JsonNode`. | ||
|
||
### Why Choose [Hyperbee.Json](https://github.com/Stillpoint-Software/Hyperbee.Json) ? | ||
|
||
- High Performance. | ||
- Supports both `JsonElement`, and `JsonNode`. | ||
- 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. | ||
|
@@ -310,38 +320,37 @@ Here is a performance comparison of various queries on the standard book store d | |
``` | ||
|
||
``` | ||
| 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 | ||
|
||
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 | ||
``` | ||
|
||
## Additioal Documentation | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 7 additions & 7 deletions
14
src/Hyperbee.Json/Descriptors/Element/ElementTypeDescriptor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.