JsonSift 1.0.0
dotnet add package JsonSift --version 1.0.0
NuGet\Install-Package JsonSift -Version 1.0.0
<PackageReference Include="JsonSift" Version="1.0.0" />
<PackageVersion Include="JsonSift" Version="1.0.0" />
<PackageReference Include="JsonSift" />
paket add JsonSift --version 1.0.0
#r "nuget: JsonSift, 1.0.0"
#:package JsonSift@1.0.0
#addin nuget:?package=JsonSift&version=1.0.0
#tool nuget:?package=JsonSift&version=1.0.0
JsonSift
A small, safe, bounded expression language over in-memory JSON
(System.Text.Json). Point it at a JsonNode and:
- navigate with
$-paths —$.user.name,$.items[0],$.items[*].id - filter arrays with one comparison —
$.items[?id == $.current.id].name - evaluate boolean conditions —
$.amount > 1000 && $.country in ['ES','PT'] - interpolate strings —
"Hi {name}"with a{hole} → pathmap
It is a deliberately small subset: no recursive descent (..), no functions,
no arithmetic, no code execution. The whole surface is hand-written and auditable —
you navigate data, nothing else. That makes it a good fit for user-supplied templates,
rules, and config where you must not hand over a general expression engine.
Install
dotnet add package JsonSift
Multi-targets net8.0, net9.0, net10.0. Only dependency: System.Text.Json (in-box).
Quickstart
using JsonSift; // SiftContext, JsonExpr, exceptions
using JsonSift.Paths; // PathExpression, CompiledPath
using JsonSift.Conditions; // ConditionParser, ConditionEvaluator
using JsonSift.Interpolation; // StringInterpolator
using System.Text.Json.Nodes;
// 1) Build the root document from heterogeneous inputs (or use any JsonNode you already have)
JsonObject root = new SiftContext()
.AddNode("payload", payloadJsonElement) // JsonElement / JsonDocument / JsonNode / any T
.AddNode("user", new { id = "u2", name = "Bob" })
.Build();
// 2) Compile once (this validates syntax and throws ExpressionParseException on errors)
CompiledPath path = PathExpression.Parse("$.user.name");
CompiledCondition cond = ConditionParser.Parse("$.payload.amount > 1000");
CompiledTemplateString tpl = StringInterpolator.Compile(
"Hi {name}", new Dictionary<string, string> { ["name"] = "$.user.name" });
// 3) Evaluate against any JsonNode root
JsonNode? name = PathExpression.ResolveSingle(path, root); // "Bob"
bool ok = ConditionEvaluator.Evaluate(cond, root); // true/false
string text = StringInterpolator.Interpolate(tpl, root); // "Hi Bob"
// Typed resolution with coercion:
string? n = JsonExpr.ResolveAs<string>(path, root);
Grammar at a glance
| Form | Meaning |
|---|---|
$.a.b / $['weird key'] |
member access |
$.a[0] |
array index |
$.a[*] |
wildcard projection → a list |
$.a[?field op operand] |
keep array elements where one comparison holds |
| operators | == != > >= < <= (filters & conditions) |
| conditions | && \|\| ! (...), x in ['a','b'], x matches 'regex', bare path = truthy |
| operand | literal ('str', number, true/false/null) or an absolute $... path |
A path with [*] or a filter yields a list; otherwise a single value.
A missing member/index resolves to null (never throws).
Two things to know
==coerces numeric strings (SQL-like):"1" == 1is true. This is not RFC 9535 behaviour — see Documents/07-vs-rfc-9535.md.- Filters use a bare field name (
[?id == ...]), not@.id. One comparison only — no&&/||/nesting inside a filter.
Documentation
Full docs live in Documents/:
- Overview — concepts, types, API map
- Grammar — paths, indices, wildcards, filters, cardinality
- Conditions — booleans,
in,matches, truthiness - Interpolation — literals, bare paths,
{holes} - SiftContext — assembling the root from
JsonElement/JsonDocument/T - Coercion — equality, ordering, dates, truthiness, to-string
- vs RFC 9535 — how this differs from standard JSONPath
License
MIT — see LICENSE.
| 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. net9.0 is compatible. 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. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.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.0.0 | 131 | 6/30/2026 |