JsonPathExpressions 1.2.0

dotnet add package JsonPathExpressions --version 1.2.0
                    
NuGet\Install-Package JsonPathExpressions -Version 1.2.0
                    
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="JsonPathExpressions" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="JsonPathExpressions" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="JsonPathExpressions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add JsonPathExpressions --version 1.2.0
                    
#r "nuget: JsonPathExpressions, 1.2.0"
                    
#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.
#:package JsonPathExpressions@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=JsonPathExpressions&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=JsonPathExpressions&version=1.2.0
                    
Install as a Cake Tool

JSONPath expressions

Nuget License


This package allows creating, parsing, modifying and analyzing JSONPath expressions.

What is JSONPath

JSONPath expressions allow specifying JSON elements to manipulate. For details see JSONPath - XPath for JSON.

Since JSONPath behavior was not standardized, different implementations work in different ways. See JSONPath Comparison for details. For any nuances the current project refers to how Json.NET works with JSONPath.

Future

There is an RFC 9535 draft for JSONPath. The current project may be changed to comply with the draft in the future.

Features

Create and modify expressions

You can create JSONPath expressions from scratch or parse existing ones:

var expr1 = new JsonPathExpression("$.a.b.c");
var expr2 = new JsonPathExpression([
    new JsonPathRootElement(),
    new JsonPathPropertyElement("a"),
    new JsonPathPropertyElement("b"),
    new JsonPathPropertyElement("c")
    ]);
// fluent syntax is safer because it restricts expression to valid form
var expr3 = JsonPathExpression.Builder.Root().Property("a").Property("b").Property("c").Build();
var expr4 = JsonPathExpression.Builder.Root()["a"]["b"]["c"].Build(); // alternative short variant
bool equal1and2 = expr1.Equals(expr2); // returns true
bool equal1and3 = expr1.Equals(expr3); // returns true
bool equal1and4 = expr1.Equals(expr4); // returns true

You can modify existing expressions:

var expr = new JsonPathExpression("$.a.b.c");
string parent = expr.RemoveLast().ToString(); // returns "$.a.b"
string child = expr.Append(new JsonPathArrayIndexElement(42)).ToString(); // returns "$.a.b.c[42]"

Analyze expressions

Check if the path is absolute
bool isAbsolute = new JsonPathExpression("$.a.b.c").IsAbsolute; // returns true because expression starts with root object
Check if the path is strict

Strict JSONPath expression points at exactly one JSON element. This check does not count expressions and slice addressing last array element ([-1:]).

bool isStrict = new JsonPathExpression("$.a[42].b[7:8]").IsStrict; // returns true because expression addresses exactly one element
isStrict = new JsonPathExpression("$.a[*].b[7]").IsStrict; // returns false because expression potentially addresses multiple elements
Work with parent/child relations
var parent = new JsonPathExpression("$.a.['b']");
var child = new JsonPathExpression("$.a.b.c.d");
bool startsWith = child.StartsWith(parent); // returns true
string relative = parent.GetRelativePathTo(child).ToString(); // returns "c.d"
var child1 = new JsonPathExpression("$.a.b.c.d");
var child2 = new JsonPathExpression("$.a.b.c.e");
string parent = child1.GetParentWith(child2).ToString(); // returns "$.a.b.c"

Check expressions for matching

You can check if one JSONPath expression matches another one.

var expr1 = new JsonPathExpression("$.a.*.c[:]");
var expr2 = new JsonPathExpression("$.a.b.c[42]");
bool? matches = expr1.Matches(expr2); // returns true

The method returns bool? because for some expression elements it's not easy or not possible to check if they exactly match. In this case null means "neither true nor false":

var expr1 = new JsonPathExpression("$.a.*.c[-1:]"); // ends with last array element
var expr2 = new JsonPathExpression("$.a.b.c[42]");
bool? matches = expr1.Matches(expr2); // returns null because it's not possible to check if 42 is the last index in the array

Details

Absolute/relative JSONPath expressions

JSONPath expressions are divided into absolute (starting with "$") and relative (not starting with "$"). To check if JSONPath expression is absolute IsAbsolute property is used:

var absolute = new JsonPathExpression("$.a.b.c");
var relative = new JsonPathExpression("a.b.c");
bool isAbsoluteAbsolute = absolute.IsAbsolute; // returns true
bool isRelativeAbsolute = relative.IsAbsolute; // returns false

There are also derived classes ensuring expression type:

var absolute = new AbsoluteJsonPathExpression("$.a.b.c"); // always starts with "$"
var relative = new RelativeJsonPathExpression("a.b.c"); // always doesn't start with "$"

Any JSONPath expression can be converted to absolute:

AbsoluteJsonPathExpression expr1 = new JsonPathExpression("$.a.b.c").ToAbsolute();
AbsoluteJsonPathExpression expr2 = new JsonPathExpression("a.b.c").ToAbsolute();
bool equals = expr1.Equals(expr2); // returns true

JSONPath elements

JSONPath expression consists of elements. Most of them are not restricted in usage but there are two special elements:

  • JsonPathRootElement - first element of an absolute JSONPath expression;
  • JsonPathRecursiveDescentElement - recursive descent (..), containing another non-special element (because .. is always folowed by another element).

For creation or modification of JSONPath expressions JsonPathRecursiveDescentElement is handy because it forces user to use another JSONPath element:

var expr = new JsonPathExpression([
    new JsonPathRootElement(),
    new JsonPathRecursiveDescentElement(new JsonPathPropertyElement("a")) // because recursive descent must be followed by another element it accepts that element as parameter
    ]); // string presentation: "$..a"

For JSONPath elements analysis JsonPathRecursiveDescentElement may cause problems because it's a special element that should be treated in a special way. To address this issue and simplify checks following JsonPathElement extension methods were added:

  • check if an element has a certain type or is a recursive descent applied to an element with a certain type:
    • IsOfType(JsonPathElementType type);
    • IsOfType(params JsonPathElementType[] types);
    • IsOfTypeInRange(JsonPathElementType firstType, JsonPathElementType lastType);
  • GetUnderlyingElement() - get element which is not recursive descent (for resursive descent JsonPathRecursiveDescentElement.AppliedToElement is returned);
  • cast element to certain type (if called on recursive descent JsonPathRecursiveDescentElement.AppliedToElement may be cast if TJsonPathElement is not JsonPathRecursiveDescentElement):
    • CastTo<TJsonPathElement>() - throws InvalidCastException if failed to cast;
    • As<TJsonPathElement>() - returns null if failed to cast.
Examples

Check expression for allowed elements:

var expr = new JsonPathExpression("$.*..a[*]");
bool isAllowedExpression = expr.Elements.All(x => x.IsOfType(
    JsonPathElementType.Root,
    JsonPathElementType.Property,
    JsonPathElementType.AnyProperty,
    JsonPathElementType.AnyArrayIndex
    )); // returns true

Check if an expression contains elements related to arrays:

var expr = new JsonPathExpression("$.*..a[*]");
bool worksWithArrays = expr.Elements.Any(x => x.IsOfTypeInRange(JsonPathElementType.ArrayIndex, JsonPathElementType.FilterExpression)); // returns true

Note: JSONPath element types may be divided into ranges:

  • JsonPathElementType.Root .. JsonPathElementType.RecursiveDescent - special elements;
  • JsonPathElementType.Property .. JsonPathElementType.PropertyList - properties;
  • JsonPathElementType.ArrayIndex .. JsonPathElementType.ArraySlice - array indexes and array slice;
  • JsonPathElementType.Expression .. JsonPathElementType.FilterExpression - expressions (related to arrays).

Get property name:

var expr = new JsonPathExpression("$.*..a");
string propertyName = expr.LastElement.CastTo<JsonPathPropertyElement>().Name; // returns "a"

Normalization

Some meanings may be expressed using different JSONPath elements. Examples:

  • [:] and [*];
  • [0:42] and [:42];
  • [0::2] and [::2];
  • [7:7] and [:0].

This can make analysis of expressions harder. To simplify it JSONPath expressions can be brought to normalized form:

string expr1 = new JsonPathExpression("$.a[:].b[0:42]").GetNormalized().ToString(); // returns "$.a[*].b[:42]"

During normalization array index list element and property list element are broken down to array index element and property element if needed. This may be helpful when an expression is constructed from scratch:

var expr1 = new JsonPathExpression([
    new JsonPathRootElement(),
    new JsonPathPropertyListElement(["a"]),
    new JsonPathArrayIndexListElement([42])
    ]).GetNormalized();
var expr2 = new JsonPathExpression([
    new JsonPathRootElement(),
    new JsonPathPropertyElement("a"),
    new JsonPathArrayIndexElement(42)
    ]);
bool equals = expr1.Equals(expr2); // returns true

Search for matching expressions

JsonPathExpressionMatchingSet<TJsonPathExpression> allows to find matching expressions for a given JSONPath expression. See example:

var expr1 = new JsonPathExpression("$.a.*.c[*]");
var expr2 = new JsonPathExpression("$.*.b.c[:]");
var expr3 = new JsonPathExpression("$.*.b.c[1::2]");

var matchingSet = new JsonPathExpressionMatchingSet<JsonPathExpression>();
matchingSet.Add(expr1);
matchingSet.Add(expr2);
matchingSet.Add(expr3);
bool matched = matchingSet.Matches(new JsonPathExpression("$.a.b.c[42]"), out var matchedBy); // matchedBy contains expr1 and expr2 because they match "$.a.b.c[42]"
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 is compatible.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.6.1

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net10.0

    • No dependencies.
  • 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
1.2.0 113 6/1/2026
1.1.2 67,852 11/13/2020
1.1.1 18,504 10/15/2020
1.1.0 671 10/13/2020
1.0.5 669 10/11/2020