Search code examples
c#.netjsonwcfjson.net

Modifying a JSON field within a collection using JObject


I'm trying to change a field value within a JSON message that is within a JSON array collection. Unfortunately the JSON.net documentation shows how to modify everything but a collection field.

With the following JSON message structure and fiddler code I need to modify the first value element field within the params array of testParams, but I can't make it work. It throws an "Object reference not set to an instance of an object" exception on the cJson["value"] = "New value"; line because cJson is null, so I must be doing something incorrectly to reference that field location. Can anyone help me resolve this?

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;

public class Program
{
    public static void Main()
    {
        String json = @"{
          'codeName': '',
          'testParams': {
            'params': [
              {
                'name': '',
                'value': ''
              },
              {
                'name': '',
                'value': ''
              }
            ]
          }
        }";

        var item = JObject.Parse(json);
        JObject cJson = (JObject)item["testParams.params[0]"]; 
        cJson["value"] = "New value";
        Console.WriteLine(item.ToString(Formatting.Indented));

    }
}

The output should look like this after the "value" field is changed.

{
  'codeName': '',
  'testParams': {
    'testobj': [
      {
        'name': '',
        'value': 'New value'
      },
      {
        'name': '',
        'value': ''
      }
    ]
  }
}

Solution

  • The problem is that you are passing a JSON path expression to the indexer on the JObject. This will not work because the indexer expects the argument string to be an actual property name. Since there's no property in the root of the JSON which is literally called testParams.params[0], the indexer will return null. If you want to use a path expression, you need to use the SelectToken() method instead.

    JObject cJson = (JObject)item.SelectToken("testParams.params[0]");
    

    Fiddle: https://dotnetfiddle.net/XXx06N

    For reference, the equivalent way to do it using the indexer syntax is like this:

    JObject cJson = (JObject)item["testParams"]["params"][0];