简体   繁体   中英

Unable to update JToken value

I'm trying to update the value of JToken but its reference is not getting updated.

JSON string:

    {
  "Title": "master",
  "Presentation": [
    {      
      "Component": {
        "Content": {
          "Title": "Set New Title",
        }
      }
    }
  ]
}

and the usage is given below

JObject jo = JObject.Parse(File.ReadAllText(file.json));
foreach (var token in jo.SelectTokens("$..Component.Content").Children())
            {
                JProperty prop = token.ToObject<JProperty>();
                prop.Value = "New Title";
            }
string jsonText = JsonConvert.SerializeObject(jo, Formatting.Indented);

In this example, I'm trying to update the value of Title property. It is getting updated within foreach, means local variable is getting updated but changes are not reflecting in main jobject.

Can anyone help me if i'm doing anything wrong?

Once you call ToObject then you are working with a copy. If instead you try this, it should work:

JObject jo = JObject.Parse(File.ReadAllText(file.json));
foreach (var prop in jo.SelectTokens("$..Component.Content")
    .Children().OfType<JProperty>())
{
    prop.Value = "New Title";
}
string jsonText = JsonConvert.SerializeObject(jo, Formatting.Indented);

or to handle multiple types of JToken s:

JObject jo = JObject.Parse(File.ReadAllText(file.json));
foreach (var token in jo.SelectTokens("$..Component.Content")
    .Children())
{
    var prop = token as JProperty;
    if (prop != null) prop.Value = "New Title";
    var array = token as JArray;
    if (array != null)
    {
        // some other logic
    }
}

string jsonText = JsonConvert.SerializeObject(jo, Formatting.Indented);

The answer from Stuart may be erroneous because "Content" may contain other children and all of theme could be renamed or their values could be changed.

I've encountered the similar issue. From the body I needed to remove value, because it was too long for logging and unnecesary, so I needed to change it's value. I could've changed it with indexer like token["name"], but "name" could be of different cases, so I needed an universal case independent way to erase it's value:

And I implemented it other way:

var jObject = JObject.Parse(body);

JToken token;
if (jObject.TryGetValue(
    Constants.FieldName,
    StringComparison.InvariantCultureIgnoreCase,
    out token))
{
    var jProperty = token.Parent as JProperty;
    if (jProperty != null)
    {
        jProperty.Value = "removed";
    }

    body = jObject.ToString(Formatting.Indented);
}

Here you have a magnificient example of how you can do this, in a proper way. Both solutions above didn't work for me, but this very simple yes. Simply work with the JToken or Object as an array. That's all.

https://www.newtonsoft.com/json/help/html/ModifyJson.htm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM