Albatross.Json
A .NET library providing extension methods for System.Text.Json and JsonNode objects.
Features
- SetValue Extension Method - Set values at any path within a JSON structure
- Case-Sensitive and Case-Insensitive Support - Control property name matching behavior via
JsonSerializerOptions - Automatic Path Creation - Intermediate objects are created automatically when navigating non-existent paths
- Array Support - Navigate and modify array elements using numeric string indices
Installation
dotnet add package Albatross.Json
SetValue Extension Method
Sets a value at the specified path within a JSON node structure.
public static JsonNode? SetValue<T>(this JsonNode? node, string[] path, T? value, JsonSerializerOptions options)
Parameters
| Parameter | Description |
|---|---|
node |
The root JSON node. If null, a new JsonObject is created. |
path |
The path segments to navigate. Use numeric strings for array indices. |
value |
The value to set at the specified path. |
options |
JsonSerializerOptions controlling serialization and case sensitivity. |
Behavior
- If path is empty, returns the serialized value directly (replaces entire node)
- Creates intermediate JsonObjects automatically when navigating non-existent paths
- Overwrites existing value nodes (JsonValue) with JsonObjects when the path continues through them
- For arrays, path segments must be valid integer indices within bounds
- Throws
ArgumentExceptionwhen an array index is out of bounds or not a valid integer
Case Sensitivity
The PropertyNameCaseInsensitive option in JsonSerializerOptions controls property name matching:
Case-Insensitive Mode
When PropertyNameCaseInsensitive = true, property lookups ignore case and preserve original property names:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var node = JsonNode.Parse("""{"UserName":"old"}""");
node = node.SetValue(["username"], "new", options);
// Result: {"UserName":"new"}
// Original "UserName" casing is preserved
Case-Sensitive Mode
When PropertyNameCaseInsensitive = false (default), different casing creates separate properties:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = false };
var node = JsonNode.Parse("""{"Name":"old"}""");
node = node.SetValue(["name"], "new", options);
// Result: {"Name":"old","name":"new"}
// Both properties coexist
Examples
Set Simple Property
var node = JsonNode.Parse("{}");
node = node.SetValue(["name"], "test", options);
// Result: {"name":"test"}
Set Nested Property
var node = JsonNode.Parse("{}");
node = node.SetValue(["level1", "level2"], "value", options);
// Result: {"level1":{"level2":"value"}}
Update Array Element
var node = JsonNode.Parse("""{"arr":[1,2,3]}""");
node = node.SetValue(["arr", "1"], 99, options);
// Result: {"arr":[1,99,3]}
Set Property Inside Array Element
var node = JsonNode.Parse("""{"items":[{"id":1},{"id":2}]}""");
node = node.SetValue(["items", "0", "name"], "first", options);
// Result: {"items":[{"id":1,"name":"first"},{"id":2}]}
Replace Entire Node
var node = JsonNode.Parse("""{"old":"data"}""");
node = node.SetValue(Array.Empty<string>(), "replaced", options);
// Result: "replaced"