Table of Contents

Invex.Extensions.Json

Lightweight, allocation-conscious utilities for flattening, unflattening, and updating System.Text.Json node trees (JsonNode / JsonObject / JsonArray) using human-readable path notation such as user:address:city.

Ideal for configuration manipulation, ETL pipelines, diffing/patching JSON documents, and round-tripping JSON to flat key/value stores (e.g., IConfiguration-style providers).

License: MIT

Features

  • 🔹 Flatten any JsonNode tree into a flat dictionary of path → value pairs
  • 🔹 Unflatten flattened pairs back into a hierarchical JsonObject
  • 🔹 Replace values at one or many paths — including inside arrays — without creating structure you didn't ask for
  • 🔹 JsonObject extension members (ToFlattenedJsonObject, ToFlattenedDictionary, ToUnflattenedJsonObject, HasNestedObjects) with full type preservation and sparse-array padding
  • 🔹 Configurable, multi-character separators (default :)
  • 🔹 No reflection, no regex on hot paths, minimal allocations
  • 🔹 Targets net10.0, net9.0, net8.0, and netstandard2.0

Installation

dotnet add package Invex.Extensions.Json

Quick start

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

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

// Flatten to path/value pairs (bracketed array indices)
IDictionary<string, string?> flat = JsonExtensions.Flatten(json);
// ["user:name"]      = "John"
// ["user:tags:[0]"]  = "admin"
// ["user:tags:[1]"]  = "user"

// Rebuild the tree
JsonObject rebuilt = JsonExtensions.Unflatten(flat);

// Update values in place (bare numeric array indices)
rebuilt.ReplaceValues(new Dictionary<string, string?>
{
    ["user:name"]    = "Jane",
    ["user:tags:1"]  = "editor",
});

Or use the type-preserving JsonObject extension members:

var obj = JsonNode.Parse("""{ "a": { "n": 42, "b": [true, null] } }""")!.AsObject();

JsonObject flatObj = obj.ToFlattenedJsonObject();   // values keep their JSON types
JsonObject roundTrip = flatObj.ToUnflattenedJsonObject();

Documentation

Topic Description
Getting started Installation, namespaces, and a guided tour
Path notation The two path conventions and when each applies
Flattening & unflattening JsonExtensions.Flatten / Unflatten in depth
JsonObject extension members ToFlattenedJsonObject, ToFlattenedDictionary, ToUnflattenedJsonObject, HasNestedObjects
Replacing values ReplaceValue / ReplaceValues semantics and fallbacks
API reference Generated API documentation

Choosing the right API

There are two complementary API surfaces — pick based on whether you need type fidelity:

JsonExtensions (static) JsonObject extension members
Array index notation Bracketed: users:[0]:name Bare numeric: users:0:name
Value representation Strings only Original JSON types preserved
Sparse array indices Applied in append order Padded with nulls
Flatten input Any JsonNode JsonObject
Best for Key/value stores, config providers Lossless round-tripping

See Path notation for the full comparison.

License

Licensed under the MIT License.