Add a JSON string to an existing one in C#

Viewed 386

I'm trying to add a JSON string to an existing one but still haven't been able to do it successfully.

This is the original string: originalJSONString

{
  "properties": [
    "property1",
    "property2"
  ]
}

And I want to add this to the original string: JSONStringIwantToAdd

{
  "filter": {
    "Name": "some filter name",
    "Parameters": {
      "LookupKey": "somekey",
      "LookupValue": "somevalue"
    }
  }
}

To make a resulting string like this: finalJSONString

{
  "properties": [
    "property1",
    "property2"
  ],
  "filter": {
    "Name": "some filter name",
    "Parameters": {
      "LookupKey": "somekey",
      "LookupValue": "somevalue"
    }
  }
}

This is my direction so far but I'm getting null in propertiesJObject and can't figure out afterwards.

Is this even the right direction I'm going?

        var originalJObj = JObject.Parse(originalJSONString);
        var tobeaddedJObj = JObject.Parse(JSONStringIwantToAdd);
        var propertiesJObject = originalJObj["properties"] as JObject;
        propertiesJObject.Add(tobeaddedJObj);
        var serializer = new JsonSerializer { ContractResolver = new CamelCasePropertyNamesContractResolver() };
        var finalJSONString = JObject.FromObject(originalJObj, serializer).ToString();

Can someone please help me with this?

Thank You for your time!

4 Answers

JSON.NET includes functionality to do exactly what you need: JContainer.Merge

Note that Merge modifies the original object, rather than returning a new one:

var original = JObject.Parse(@"{
  ""properties"": [
    ""property1"",
    ""property2""
  ]
}");

var toAdd = JObject.Parse(@"{
  ""filter"": {
    ""Name"": ""some filter name"",
    ""Parameters"": {
      ""LookupKey"": ""somekey"",
      ""LookupValue"": ""somevalue""
    }
  }
}");

original.Merge(toAdd, new JsonMergeSettings
{
    // union array values together to avoid duplicates
    MergeArrayHandling = MergeArrayHandling.Union
});

Fiddle link: https://dotnetfiddle.net/o51GuA

You can do this without explicitly using a serializer.

This code adds the first property from JSONStringIwantToAdd to originalJSONString:

var originalJson = "{\r\n  \"properties\": [\r\n    \"property1\",\r\n    \"property2\"\r\n  ]\r\n}";

var extraJson = "{\r\n  \"filter\": {\r\n    \"Name\": \"some filter name\",\r\n    \"Parameters\": {\r\n      \"LookupKey\": \"somekey\",\r\n      \"LookupValue\": \"somevalue\"\r\n    }\r\n  }\r\n}";

var original = JObject.Parse(originalJson);
var extra = JObject.Parse(extraJson);
var newProperty = extra.Children().First() as JProperty;

original.Add(newProperty.Name, newProperty.Value);

var newJson = original.ToString();

Output:

{
  "properties": [
    "property1",
    "property2"
  ],
  "filter": {
    "Name": "some filter name",
    "Parameters": {
      "LookupKey": "somekey",
      "LookupValue": "somevalue"
    }
  }
}

This should work, the main issue was not accessing the filter property when adding it to the jobject. I would recommend adding some safeguards like checking for existing properties, this may not be as performant as possible. If speed is important you may have to write your own serializer/deserializer for json.net.

    [Test]
    public void AugmentJsonObjectTest()
    {
        // Given
        var originalString = "{  \"properties\": [    \"property1\",    \"property2\"  ]}";
        var stringToBeAdded = "{  \"filter\": {    \"Name\": \"some filter name\",    \"Parameters\": {      \"LookupKey\": \"somekey\",      \"LookupValue\": \"somevalue\"    }  }}";

        // When
        var originalObject = JObject.Parse(originalString);
        var objectToBeAdded = JObject.Parse(stringToBeAdded);
        originalObject.Add("filter", objectToBeAdded["filter"]);
        var mergedObjectAsString = originalObject.ToString();

        // Then
        var expectedResult =
            "{  \"properties\": [    \"property1\",    \"property2\"  ],  \"filter\": {    \"Name\": \"some filter name\",    \"Parameters\": {      \"LookupKey\": \"somekey\",      \"LookupValue\": \"somevalue\"    }  }}";
        // Parsing and toString to avoid any formatting issues
        Assert.AreEqual(JObject.Parse(expectedResult).ToString(), mergedObjectAsString);
    }

using Expando

using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using Newtonsoft.Json;

namespace jsonConcat {
class Program {
    static void Main (string[] args) {
        ExpandoObject inputData;
        ExpandoObject appendData;
        using (TextReader inputReader = new StreamReader ("originalData.json"))
        using (TextReader appendReader = new StreamReader ("appendData.json")) {
            inputData = JsonConvert.DeserializeObject<ExpandoObject> (inputReader.ReadToEnd ());
            appendData = JsonConvert.DeserializeObject<ExpandoObject> (appendReader.ReadToEnd ());
        }
        foreach (var item in appendData) {
            inputData.TryAdd (item.Key.ToString (), item.Value);
        }
        using (TextWriter outputWriter = new StreamWriter ("outputData.json")) {
            outputWriter.Write (JsonConvert.SerializeObject (inputData));
        }
    }
}

}

Related