Invex.Extensions.Json 1.1.0

dotnet add package Invex.Extensions.Json --version 1.1.0
                    
NuGet\Install-Package Invex.Extensions.Json -Version 1.1.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="Invex.Extensions.Json" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Invex.Extensions.Json" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Invex.Extensions.Json" />
                    
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 Invex.Extensions.Json --version 1.1.0
                    
#r "nuget: Invex.Extensions.Json, 1.1.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 Invex.Extensions.Json@1.1.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=Invex.Extensions.Json&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Invex.Extensions.Json&version=1.1.0
                    
Install as a Cake Tool

Invex.Extensions.Json

Build NuGet License: MIT .NET

Invex.Extensions.Json is a small, allocation-conscious library for flattening, unflattening, and updating System.Text.Json node trees (JsonNode, JsonObject, and JsonArray) with readable paths such as user:address:city. It is useful for configuration and environment-variable adapters, ETL pipelines, JSON diffing or patching, and exchanging JSON with flat key/value stores.

Features

  • Flatten any node. Turn any JsonNode into path/value pairs.
  • Rebuild hierarchies. Recreate a JsonObject from flattened pairs.
  • Update in place. Replace one or many values in an existing JsonObject, including array elements.
  • Type preservation. Keep JSON value types when flattening to a JsonObject.
  • Configurable separators. Use any separator, including multi-character ones such as "__".
  • Lean hot paths. No reflection or regular expressions when flattening and unflattening.

Installation

dotnet add package Invex.Extensions.Json

The package targets net10.0 and netstandard2.0, and exposes the Invex.Extensions.Json namespace. The netstandard2.0 target includes a System.Text.Json package dependency.

Quick start

using System.Text.Json.Nodes;
using Invex.Extensions.Json;

var json = JsonNode.Parse("""
{
  "user": {
    "name": "John",
    "tags": ["admin", "user"]
  }
}
""")!;

// String-valued flattening uses bracketed array indices.
IDictionary<string, string?> flat = JsonExtensions.Flatten(json);
// user:name       = "John"
// user:tags:[0]   = "admin"
// user:tags:[1]   = "user"

// The matching operation rebuilds the hierarchy.
JsonObject rebuilt = JsonExtensions.Unflatten(flat);

// Replacements mutate the existing object and use bare numeric indices.
rebuilt.ReplaceValues(new Dictionary<string, string?>
{
    ["user:name"] = "Jane",
    ["user:tags:1"] = "editor",
});

Usage

Choose an API surface

The library has two complementary path and value models. Pair operations from the same column when round-tripping.

JsonExtensions JsonObject extension members
Flattening input Any JsonNode JsonObject
Array path syntax Bracketed: users:[0]:name Bare numeric: users:0:name
Flattened values string? Original JSON nodes, or string? for the dictionary method
Unflattened arrays Append order; no sparse padding Numeric indices; sparse indices padded with null
Best suited to Configuration and string key/value stores Lossless JSON round-tripping

See Introduction for when to use each surface.

Flatten for a key/value store

JsonExtensions.Flatten returns string values (JSON null becomes a null value), and Unflatten rebuilds a JsonObject whose leaves are all JSON strings. Use the same separator for both halves of a round trip:

var flat = JsonExtensions.Flatten(json, separator: "__");
var rebuilt = JsonExtensions.Unflatten(flat, separator: "__");

Property names are not escaped, so pick a separator that never occurs in them. See Flattening and Unflattening and Path Notation.

Round-trip without losing value types

var source = JsonNode.Parse(
    """{ "a": { "number": 42, "enabled": true, "items": [null, "x"] } }""")!
    .AsObject();

JsonObject flatObject = source.ToFlattenedJsonObject();
// a:number = 42, a:enabled = true, a:items:0 = null, a:items:1 = "x"

JsonObject roundTrip = flatObject.ToUnflattenedJsonObject();
Dictionary<string, string?> flatDictionary = source.ToFlattenedDictionary();
bool hasNestedValues = source.HasNestedObjects();

Leaf nodes are deep-cloned in both directions, so results never share mutable nodes with their source. See JsonObject Extension Members.

Replace values in place

ReplaceValue and ReplaceValues modify the supplied JsonObject and return the same instance. Replacement values are stored as JSON strings (or JSON null), and no intermediate objects or arrays are ever created. ReplaceValues can step into existing arrays with bare numeric segments such as users:0:name; a bracketed [0] is treated as a literal property name.

var obj = JsonNode.Parse("""
{ "user": { "address": { "city": "NYC" } }, "users": [ { "name": "A" } ] }
""")!.AsObject();

obj.ReplaceValue("user:address:city", "LA")
   .ReplaceValues(new Dictionary<string, string?> { ["users:0:name"] = "Alpha" });

See Replacing Values for the complete traversal and fallback rules.

Documentation

Full documentation: https://invex-games.github.io/json-extensions/

Guide Contents
Introduction What the library is for, the two API surfaces, and design principles
Getting Started Installation, namespaces, and guided examples
Path Notation Array conventions, separators, values, and edge cases
Flattening and Unflattening JsonExtensions.Flatten and Unflatten
JsonObject Extension Members Type-preserving flattening and reconstruction
Replacing Values In-place updates, arrays, and fallbacks
API Reference Generated reference for every public type

Development

The repository builds with the .NET SDK selected by global.json. From the repository root:

dotnet build Invex.Extensions.Json.slnx
dotnet test Invex.Extensions.Json.slnx

The documentation site is built with DocFX from the conceptual pages in docs/ and the XML doc comments in the source. Build or preview it through the Atom build:

dotnet run --project _atom -- BuildDocs
dotnet run --project _atom -- ServeDocs

(atom BuildDocs and atom ServeDocs when the Atom tool is installed.) To run DocFX directly instead:

dotnet tool install -g docfx
docfx docfx.json --serve

Then browse to http://localhost:8080.

License

Licensed under the MIT License.

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 was computed.  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 was computed. 
.NET Framework net461 was computed.  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.

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.1.0 50 10/22/2026
1.1.0-rc.6 48 10/22/2026
1.1.0-rc.4 54 10/22/2026
1.1.0-rc.2 49 10/16/2026
1.0.0 91 10/15/2026
0.4.0-rc.30 49 10/15/2026
0.4.0-rc.28 49 10/14/2026
0.4.0-rc.26 52 10/14/2026
0.4.0-rc.24 46 10/14/2026
0.4.0-rc.22 47 10/14/2026
0.4.0-rc.20 56 10/14/2026
0.4.0-rc.16 48 10/13/2026
0.4.0-rc.10 68 9/11/2026
0.4.0-rc.8 76 8/28/2026
0.4.0-rc.6 71 8/21/2026
0.4.0-rc.4 84 8/14/2026
0.4.0-rc.2 76 8/7/2026
0.3.0 122 8/3/2026
0.3.0-rc.5 79 8/3/2026
0.3.0-rc.4 80 7/24/2026
Loading failed