Recently at work, I have a requirement to merge two json strings. Basically, I want to achieve what the spread operator does in Javascript.
For examples, let’s say we have a json string as below.
{
'ArticleName': 'Sample article name',
'PublishedDate': '10 Jan 2019',
'IsPublished': false,
'Tags': [ 'Technology' ]
}
And we want to merge the below json string
{
'IsPublished': true,
'Tags': [ 'C#', 'Programming' ]
}
The result we want to achieve is as followed
{
'ArticleName': 'Sample article name',
'PublishedDate': '10 Jan 2019',
'IsPublished': true,
'Tags': [ 'C#', 'Programming' ]
}
After some research, I found that I can use the Merge method JObject to merge one to the other.
JObject object1 = JObject.Parse(@"{
'ArticleName': 'Sample article name',
'PublishedDate': '10 Jan 2019',
'IsPublished': false,
'Tags': [ 'Technology' ]
}");
JObject object2 = JObject.Parse(@"{
'IsPublished': true,
'Tags': [ 'C#', 'Programming' ]
}");
object1.Merge(object2, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Merge
});
string json = object1.ToString();

I thought this would work. However, the json strings I have to merge at work are a lot more complex than these examples. The resulted merged json string does not pass the expected string in my unit test.
Let’s make our example above to include an array of more complex objects
JObject object1 = JObject.Parse(@"{
'ArticleName': 'Sample article name',
'PublishedDate': '10 Jan 2019',
'IsPublished': false,
'Tags': [ 'Technology' ],
'Commentors': [
{
'Name': 'John Nerks',
'Comments': [ 'ABC', 'XYZ' ],
'DateJoined': '20 Feb 2018'
}
]}");
JObject object2 = JObject.Parse(@"{
'IsPublished': true,
'Tags': [ 'C#', 'Programming' ],
'Commentors': [
{
'Name': 'Jane Smith',
'Comments': [ 'QWERTY' ]
}
]}");
object1.Merge(object2, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Merge
});
string json = object1.ToString();
I would expect the result to be
{
'ArticleName': 'Sample article name',
'PublishedDate': '10 Jan 2019',
'IsPublished': true,
'Tags': [ 'C#', 'Programming' ],
'Commentors':
[{
'Name': 'Jane Smith',
'Comments': [ 'QWERTY' ]
}]
}
But the actual result is

To fix it, simply change the JsonMergeSettings to be
new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Replace,
MergeNullValueHandling = MergeNullValueHandling.Merge,
}
