Simply and elegantly merge values into an existing JSON object
JsonMerge is a lightweight, high-performance .NET library for recursively merging JSON objects. It provides a simple API to combine JSON structures while intelligently handling nested objects, with merge values taking precedence over existing values.
Perfect for configuration management, API response merging, template systems, and any scenario where you need to overlay JSON data structures.
- Recursive Deep Merge: Automatically merges nested JSON objects at any depth
- Type-Safe: Leverages
System.Text.Json
for robust JSON parsing and manipulation - Flexible API: Choose between exception-throwing or Try pattern methods
- Smart Overwriting: Merge values override existing values when keys match
- Type Preservation: Handles all JSON types (strings, numbers, booleans, null, objects, arrays)
- Multi-Framework: Supports .NET 8.0, .NET Standard 2.0, and .NET Standard 2.1
Install via NuGet Package Manager:
dotnet add package JsonMerge
Or via Package Manager Console:
Install-Package JsonMerge
Or add directly to your .csproj
file:
<PackageReference Include="JsonMerge" Version="1.0.0" />
using JsonMerge;
// Basic merge - add new properties
string input = "{\"name\":\"John\",\"age\":30}";
string merge = "{\"city\":\"New York\",\"active\":true}";
string result = JsonMerger.MergeJson(input, merge);
// Result: {"name":"John","age":30,"city":"New York","active":true}
// Overwrite existing properties
string input2 = "{\"name\":\"John\",\"age\":30}";
string merge2 = "{\"age\":35,\"role\":\"admin\"}";
string result2 = JsonMerger.MergeJson(input2, merge2);
// Result: {"name":"John","age":35,"role":"admin"}
// Recursive merge of nested objects
string input3 = "{\"user\":{\"name\":\"John\",\"email\":\"john@example.com\"}}";
string merge3 = "{\"user\":{\"age\":30,\"verified\":true}}";
string result3 = JsonMerger.MergeJson(input3, merge3);
// Result: {"user":{"name":"John","email":"john@example.com","age":30,"verified":true}}
Merges two JSON objects, with merge values overwriting input values for matching keys.
Parameters:
inputJson
- The base JSON object (required, non-null, non-empty)mergeJson
- The JSON object to merge into the input (required, non-null, non-empty)
Returns: A JSON string containing the merged result
Throws:
ArgumentNullException
- If either parameter is null or emptyArgumentException
- If either parameter is not a valid JSON objectJsonException
- If JSON parsing fails
Attempts to merge JSON objects with safe error handling.
Parameters:
inputJson
- The base JSON objectmergeJson
- The JSON object to mergeresult
- Output parameter containing the merged JSON string, or null if merge fails
Returns: true
if merge succeeded, false
otherwise
// Merge default config with user overrides
string defaultConfig = "{\"timeout\":30,\"retries\":3,\"logging\":{\"level\":\"info\"}}";
string userConfig = "{\"timeout\":60,\"logging\":{\"level\":\"debug\",\"verbose\":true}}";
string finalConfig = JsonMerger.MergeJson(defaultConfig, userConfig);
// Result: {"timeout":60,"retries":3,"logging":{"level":"debug","verbose":true}}
// Combine partial API responses
string baseResponse = "{\"user\":{\"id\":123,\"name\":\"Alice\"}}";
string additionalData = "{\"user\":{\"email\":\"alice@example.com\",\"role\":\"admin\"},\"timestamp\":\"2025-01-15T10:30:00Z\"}";
string combined = JsonMerger.MergeJson(baseResponse, additionalData);
// Apply template overrides
string template = "{\"layout\":\"grid\",\"theme\":\"light\",\"settings\":{\"sidebar\":true}}";
string customizations = "{\"theme\":\"dark\",\"settings\":{\"sidebar\":false,\"animations\":true}}";
string applied = JsonMerger.MergeJson(template, customizations);
string input = LoadFromDatabase();
string patch = GetUserInput();
if (JsonMerger.TryMergeJson(input, patch, out string result))
{
Console.WriteLine($"Merge successful: {result}");
}
else
{
Console.WriteLine("Merge failed - invalid JSON or incompatible types");
}
- Adding new properties: New keys from merge JSON are added to result
- Overwriting values: Matching keys get overwritten with merge values
- Nested object merging: Objects are recursively merged at all depths
- Type changes: A property can change type (e.g., number → string)
- All JSON types: Strings, numbers, booleans, null, objects, and arrays
- Deep structures: Unlimited nesting depth supported
- Special characters: Unicode, whitespace, and escape sequences
- Null or empty inputs: Both parameters must be non-null and non-empty
- Invalid JSON syntax: Malformed JSON throws exceptions
- Array inputs: Root elements must be objects
{}
, not arrays[]
- Primitive inputs: Root elements must be objects, not primitives (
123
,"string"
, etc.)
Arrays are treated as atomic values and are replaced entirely:
string input = "{\"tags\":[\"javascript\",\"nodejs\"]}";
string merge = "{\"tags\":[\"python\",\"django\"]}";
string result = JsonMerger.MergeJson(input, merge);
// Result: {"tags":["python","django"]} - NOT ["javascript","nodejs","python","django"]
Merging with an empty object leaves the input unchanged:
string input = "{\"a\":1,\"b\":2}";
string merge = "{}";
string result = JsonMerger.MergeJson(input, merge);
// Result: {"a":1,"b":2}
When a value's type changes, the new type completely replaces the old:
// Object replaced by primitive
string input = "{\"data\":{\"nested\":true}}";
string merge = "{\"data\":\"simple string\"}";
string result = JsonMerger.MergeJson(input, merge);
// Result: {"data":"simple string"}
// Primitive replaced by object
string input2 = "{\"data\":123}";
string merge2 = "{\"data\":{\"complex\":true}}";
string result2 = JsonMerger.MergeJson(input2, merge2);
// Result: {"data":{"complex":true}}
- Time Complexity: O(n + m) where n is the size of input and m is the size of merge
- Space Complexity: O(n + m) for the result object
- Deep Cloning: Values are deep cloned to prevent reference issues
- Zero Allocations: Minimal allocations beyond necessary result structures
Target Framework | Version |
---|---|
.NET | 8.0+ |
.NET Standard | 2.0+ |
.NET Standard | 2.1+ |
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License - see the LICENSE.md file for details.
Icon designed by VeryIcon.
- NuGet Package: https://nuget.org/packages/JsonMerge
- GitHub Repository: https://github.com/jchristn/jsonmerge
- Issue Tracker: https://github.com/jchristn/jsonmerge/issues
Made with ❤️ by Joel Christner