{"id":37034517,"url":"https://github.com/gxost/jsonpathexpressions","last_synced_at":"2026-01-14T04:02:39.402Z","repository":{"id":62997906,"uuid":"302430604","full_name":"Gxost/JsonPathExpressions","owner":"Gxost","description":"Allows to create, parse, modify and analyze JSONPath expressions","archived":false,"fork":false,"pushed_at":"2020-11-13T08:36:17.000Z","size":240,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-29T04:46:23.712Z","etag":null,"topics":["jsonpath","jsonpath-expression"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/JsonPathExpressions","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Gxost.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-08T18:36:29.000Z","updated_at":"2022-11-10T14:57:11.000Z","dependencies_parsed_at":"2022-11-10T16:00:45.166Z","dependency_job_id":null,"html_url":"https://github.com/Gxost/JsonPathExpressions","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/Gxost/JsonPathExpressions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gxost%2FJsonPathExpressions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gxost%2FJsonPathExpressions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gxost%2FJsonPathExpressions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gxost%2FJsonPathExpressions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gxost","download_url":"https://codeload.github.com/Gxost/JsonPathExpressions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gxost%2FJsonPathExpressions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408977,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jsonpath","jsonpath-expression"],"created_at":"2026-01-14T04:02:38.867Z","updated_at":"2026-01-14T04:02:39.393Z","avatar_url":"https://github.com/Gxost.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JSONPath expressions\n\n[![Nuget](https://img.shields.io/nuget/v/JsonPathExpressions)](https://www.nuget.org/packages/JsonPathExpressions) [![License](https://img.shields.io/github/license/Gxost/JsonPathExpressions)](https://github.com/Gxost/JsonPathExpressions/blob/master/LICENSE.md) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Gxost_JsonPathExpressions\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=Gxost_JsonPathExpressions) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=Gxost_JsonPathExpressions\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=Gxost_JsonPathExpressions)\n\n----\n\nThis package allows to create, parse, modify and analyze JSONPath expressions.\n\n## What is JSONPath\n\nJSONPath expressions allow to specify JSON elements to manipulate. For details see [JSONPath - XPath for JSON](https://goessner.net/articles/JsonPath/).\n\nSince JSONPath behaviour is not standardized different implementations work in different ways. See [JSONPath Comparison](https://cburgmer.github.io/json-path-comparison/) for details. For any nuances current project refers to how [Json.NET](https://www.newtonsoft.com/json) works with JSONPath.\n\n## Features\n\n### Create and modify expressions\n\nYou can create JSONPath expressions from scratch or parse existing ones:\n\n```csharp\nvar expr1 = new JsonPathExpression(\"$.a.b.c\");\nvar expr2 = new JsonPathExpression(new JsonPathElement[] {\n    new JsonPatheRootElement(),\n    new JsonPathPropertyElement(\"a\"),\n    new JsonPathPropertyElement(\"b\"),\n    new JsonPathPropertyElement(\"c\")\n    });\n// fluent syntax is safer because it restricts expression to valid form\nvar expr3 = JsonPathExpression.Builder.Root().Property(\"a\").Property(\"b\").Property(\"c\").Build();\nvar expr4 = JsonPathExpression.Builder.Root()[\"a\"][\"b\"][\"c\"].Build(); // alternative short variant\nbool equal1and2 = expr1.Equals(expr2); // returns true\nbool equal1and3 = expr1.Equals(expr3); // returns true\nbool equal1and4 = expr1.Equals(expr4); // returns true\n```\n\nYou can modify existing expressions:\n\n```csharp\nvar expr = new JsonPathExpression(\"$.a.b.c\");\nstring parent = expr.RemoveLast().ToString(); // returns \"$.a.b\"\nstring child = expr.Append(new JsonPathArrayIndexElement(42)).ToString(); // returns \"$.a.b.c[42]\"\n```\n\n### Analyze expressions\n\n#### Check if path is absolute\n\n```csharp\nbool isAbsolute = new JsonPathExpression(\"$.a.b.c\").IsAbsolute; // returns true because expression starts with root object\n```\n\n#### Check if path is strict\n\nStrict JSONPath expression points at exactly one JSON element. This check does not count expressions and slice addressing last array element (`[-1:]`).\n\n```csharp\nbool isStrict = new JsonPathExpression(\"$.a[42].b[7:8]\").IsStrict; // returns true because expression addresses exactly one element\nisStrict = new JsonPathExpression(\"$.a[*].b[7]\").IsStrict; // returns false because expression potentially addresses multiple elements\n```\n\n#### Work with parent/child relations\n\n```csharp\nvar parent = new JsonPathExpression(\"$.a.['b']\");\nvar child = new JsonPathExpression(\"$.a.b.c.d\");\nbool startsWith = child.StartsWith(parent); // returns true\nstring relative = parent.GetRelativePathTo(child).ToString(); // returns \"c.d\"\n```\n\n```csharp\nvar child1 = new JsonPathExpression(\"$.a.b.c.d\");\nvar child2 = new JsonPathExpression(\"$.a.b.c.e\");\nstring parent = child1.GetParentWith(child2).ToString(); // returns \"$.a.b.c\"\n```\n\n### Check expressions for matching\n\nYou can check if one JSONPath expression matches another one.\n\n```csharp\nvar expr1 = new JsonPathExpression(\"$.a.*.c[:]\");\nvar expr2 = new JsonPathExpression(\"$.a.b.c[42]\");\nbool? matches = expr1.Matches(expr2); // returns true\n```\n\nThe 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\":\n\n```csharp\nvar expr1 = new JsonPathExpression(\"$.a.*.c[-1:]\"); // ends with last array element\nvar expr2 = new JsonPathExpression(\"$.a.b.c[42]\");\nbool? matches = expr1.Matches(expr2); // returns null because it's not possible to check if 42 is the last index in the array\n```\n\n## Details\n\n### Absolute/relative JSONPath expressions\n\nJSONPath expressions are divided into absolute (starting with \"$\") and relative (not starting with \"$\"). To check if JSONPath expression is absolute IsAbsolute property is used:\n\n```csharp\nvar absolute = new JsonPathExpression(\"$.a.b.c\");\nvar relative = new JsonPathExpression(\"a.b.c\");\nbool isAbsoluteAbsolute = absolute.IsAbsolute; // returns true\nbool isRelativeAbsolute = relative.IsAbsolute; // returns false\n```\n\nThere are also derived classes ensuring expression type:\n\n```csharp\nvar absolute = new AbsoluteJsonPathExpression(\"$.a.b.c\"); // always starts with \"$\"\nvar relative = new RelativeJsonPathExpression(\"a.b.c\"); // always doesn't start with \"$\"\n```\n\nAny JSONPath expression can be converted to absolute:\n\n```csharp\nAbsoluteJsonPathExpression expr1 = new JsonPathExpression(\"$.a.b.c\").ToAbsolute();\nAbsoluteJsonPathExpression expr2 = new JsonPathExpression(\"a.b.c\").ToAbsolute();\nbool equals = expr1.Equals(expr2); // returns true\n```\n\n### JSONPath elements\n\nJSONPath expression consists of elements. Most of them are not restricted in usage but there are two special elements:\n- `JsonPathRootElement` - first element of an absolute JSONPath expression;\n- `JsonPathRecursiveDescentElement` - recursive descent (`..`), containing another non-special element (because `..` is always folowed by another element).\n\nFor creation or modification of JSONPath expressions `JsonPathRecursiveDescentElement` is handy because it forces user to use another JSONPath element:\n\n```csharp\nvar expr = new JsonPathExpression(new JsonPathElement[]{\n    new JsonPathRootElement(),\n    new JsonPathRecursiveDescentElement(new JsonPathPropertyElement(\"a\")) // because recursive descent must be followed by another element it accepts that element as parameter\n    }); // string presentation: \"$..a\"\n```\n\nFor 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:\n- check if element has certain type or is a recursive descent applied to element with certain type:\n  - `IsOfType(JsonPathElementType type)`;\n  - `IsOfType(params JsonPathElementType[] types)`;\n  - `IsOfTypeInRange(JsonPathElementType firstType, JsonPathElementType lastType)`;\n- `GetUnderlyingElement()` - get element which is not recursive descent (for resursive descent `JsonPathRecursiveDescentElement.AppliedToElement` is returned);\n- cast element to certain type (if called on recursive descent `JsonPathRecursiveDescentElement.AppliedToElement` may be cast if `TJsonPathElement` is not `JsonPathRecursiveDescentElement`):\n  - `CastTo\u003cTJsonPathElement\u003e()` - throws `InvalidCastException` if failed to cast;\n  - `As\u003cTJsonPathElement\u003e()` - returns `null` if failed to cast.\n\n#### Examples\n\nCheck expression for allowed elements:\n\n```csharp\nvar expr = new JsonPathExpression(\"$.*..a[*]\");\nbool isAllowedExpression = expr.Elements.All(x =\u003e x.IsOfType(\n    JsonPathElementType.Root,\n    JsonPathElementType.Property,\n    JsonPathElementType.AnyProperty,\n    JsonPathElementType.AnyArrayIndex\n    )); // returns true\n```\n\nCheck if expression contains elements related to arrays:\n\n```csharp\nvar expr = new JsonPathExpression(\"$.*..a[*]\");\nbool worksWithArrays = expr.Elements.Any(x =\u003e x.IsOfTypeInRange(JsonPathElementType.ArrayIndex, JsonPathElementType.FilterExpression)); // returns true\n```\n\nNote: JSONPath element types may be divided into ranges:\n- `JsonPathElementType.Root` .. `JsonPathElementType.RecursiveDescent` - special elements;\n- `JsonPathElementType.Property` .. `JsonPathElementType.PropertyList` - properties;\n- `JsonPathElementType.ArrayIndex` .. `JsonPathElementType.ArraySlice` - array indexes and array slice;\n- `JsonPathElementType.Expression` .. `JsonPathElementType.FilterExpression` - expressions (related to arrays).\n\nGet property name:\n\n```csharp\nvar expr = new JsonPathExpression(\"$.*..a\");\nstring propertyName = expr.LastElement.CastTo\u003cJsonPathPropertyElement\u003e().Name; // returns \"a\"\n```\n\n### Normalization\n\nSome meanings may be expressed using different JSONPath elements. Examples:\n- `[:]` and `[*]`;\n- `[0:42]` and `[:42]`;\n- `[0::2]` and `[::2]`;\n- `[7:7]` and `[:0]`.\n\nThis can make analysis of expressions harder. To simplify it JSONPath expressions can be brought to normalized form:\n\n```csharp\nstring expr1 = new JsonPathExpression(\"$.a[:].b[0:42]\").GetNormalized().ToString(); // returns \"$.a[*].b[:42]\"\n```\n\nDuring 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:\n\n```csharp\nvar expr1 = new JsonPathExpression(new JsonPathElement[]{\n    new JsonPathRootElement(),\n    new JsonPathPropertyListElement(new []{ \"a\" }),\n    new JsonPathArrayIndexListElement(new [] { 42 })\n    }).GetNormalized();\nvar expr2 = new JsonPathExpression(new JsonPathElement[]{\n    new JsonPathRootElement(),\n    new JsonPathPropertyElement(\"a\"),\n    new JsonPathArrayIndexElement(42)\n    });\nbool equals = expr1.Equals(expr2); // returns true\n```\n\n### Search for matching expressions\n\n`JsonPathExpressionMatchingSet\u003cTJsonPathExpression\u003e` allows to find matching expressions for a given JSONPath expression. See example:\n\n```csharp\nvar expr1 = new JsonPathExpression(\"$.a.*.c[*]\");\nvar expr2 = new JsonPathExpression(\"$.*.b.c[:]\");\nvar expr3 = new JsonPathExpression(\"$.*.b.c[1::2]\");\n\nvar matchingSet = new JsonPathExpressionMatchingSet\u003cJsonPathExpression\u003e();\nmatchingSet.Add(expr1);\nmatchingSet.Add(expr2);\nmatchingSet.Add(expr3);\nbool matched = matchingSet.Matches(new JsonPathExpression(\"$.a.b.c[42]\"), out var matchedBy); // matchedBy contains expr1 and expr2 because they match \"$.a.b.c[42]\"\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgxost%2Fjsonpathexpressions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgxost%2Fjsonpathexpressions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgxost%2Fjsonpathexpressions/lists"}