Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Newtonsoft update JObject from JSON path?

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.

like image 894
PMOrion Avatar asked Mar 08 '16 17:03

PMOrion


People also ask

What is JSON path expression?

JsonPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination with an XML document. The "root member object" in JsonPath is always referred to as $ regardless if it is an object or array. JsonPath expressions can use the dot–notation. $.store.book[0].title.

Can not add JValue to JObject?

You are getting this error because you are trying to construct a JObject with a string (which gets converted into a JValue ). A JObject cannot directly contain a JValue , nor another JObject , for that matter; it can only contain JProperties (which can, in turn, contain other JObjects , JArrays or JValues ).

Is JObject parse slow?

That being said, it's known that parsing to JObject can be slower than deserializing -- see stackify.com/top-11-json-performance-usage-tips which states, Parsing generic JSON to a JSON.net JObject ... is slower (~20%) than reading that data in to a defined class type.

What is JObject and JToken?

The JToken hierarchy looks like this: JToken - abstract base class JContainer - abstract base class of JTokens that can contain other JTokens JArray - represents a JSON array (contains an ordered list of JTokens) JObject - represents a JSON object (contains a collection of JProperties) JProperty - represents a JSON ...


2 Answers

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";
like image 61
Jeff Mercado Avatar answered Oct 04 '22 18:10

Jeff Mercado


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)

like image 43
S.Mishra Avatar answered Oct 04 '22 18:10

S.Mishra