8

I am aware of using the select tokens function to pass a json path. For example:

JObject jObect = JObject.Parse("{some json string}");
JToken jToken = jObject.SelectToken("root.item[0].myProperty"); 

What I am looking for is a simple manner to update the original JObject at the given JSON path?

jObject[jsonPath] = "My New Value" 

Obviously that takes an object key and not JSON path. Thanks.

Phuc Thai
  • 718
  • 7
  • 17
PMOrion
  • 169
  • 2
  • 10
  • 1
    Related: see [Editing JSON using JSONPath](https://stackoverflow.com/questions/35799010/editing-json-using-jsonpath/35804255#35804255) – dbc Mar 08 '16 at 17:50

3 Answers3

8

Json paths (and xpaths for that matter) are used to get items from a hierarchy, not to set them. You need to get the parent object using the JSON path then set the property through normal means.

var parent = jObject.SelectToken("root.item[0]");
parent["myProperty"] = "My New Value";
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • Good deal. I suppose I can tokenize theJSON path and pull the property name out since it should always be the last item in the path. – PMOrion Mar 08 '16 at 17:55
  • 2
    In newtonsoft.json system have "replace" function that could set the value directly the the token – Thaina Yu Jan 28 '19 at 09:39
  • Is there a way to modify the JSON at that path in such a way that would create any missing tokens in the path? So when you try to set "root.item[0].myProperty" but only the "root" object exists it would not only set "myProperty" but also first create an object to contain that property and an array to contain that object and an "item" property to contain that array. – Kyle Delaney Feb 26 '20 at 01:06
  • 1
    @KyleDelaney I don't think that would be possible in general. If you needed that functionality, you could definitely code it up in an extension method or something. That would involve parsing the jsonpath string, interpreting what the each part of the path implies about the object hierarchy, and navigating/creating objects as it goes. It shouldn't be too difficult as there are very straightforward rules. – Jeff Mercado Feb 26 '20 at 01:12
  • @Thaina has the best answer – triple.vee May 18 '21 at 19:18
3

I think @dbc has given a good extension to allow us to update the json object values. Can find his answer here.

But, I would put here a solution that I made with the help of above answer:

public static class JsonExtensions
{
    public static JObject ReplacePath<T>(this JToken root, string path, T newValue)
    {
        if (root == null || path == null)
        {
            throw new ArgumentNullException();
        }

        foreach (var value in root.SelectTokens(path).ToList())
        {
            if (value == root)
            {
                root = JToken.FromObject(newValue);
            }
            else
            {
                value.Replace(JToken.FromObject(newValue));
            }
        }

        return (JObject)root;
    }
}

What you can do it, using above method, you can pass the JObject, the jsonPath and the value you want to replace. So, in your case the calling method would look like this:

var jsonObj = JObject.Parse("{some json string}");   
jsonObj = JsonExtensions.ReplacePath(jsonObj,
                                         "$. root.item[0].myProperty",
                                         "My New Value");

Hope this will work for you!

You can find some examples I put in fiddle (https://dotnetfiddle.net/ZrS2iV)

Ciaran Gallagher
  • 3,895
  • 9
  • 53
  • 97
S.Mishra
  • 3,394
  • 28
  • 20
1

You can replace function of Jtoken to update the value.

var parseResponse = JToken.Parse(jsonString);
//This commented code will update all the myproperty value in the item array
//var selectedPath = parseResponse.SelectToken("$.root.item[*].myProperty");
var selectedPath = parseResponse.SelectToken("$.root.item[0].myProperty");
if(selectedPath!=null){
selectedPath.Replace(newValue);
}

ankit
  • 111
  • 1
  • 5