I want to add a new JProperty to a JSON object using a string path. I'm retrieving an existing path and then adding a new value proximal to it. It seems no matter how I select a token, or no matter what Add method I call (most relevant is AddAfterSelf) or what I supply as a new value, I receive the exception:
Run-time exception (line 9): Newtonsoft.Json.Linq.JProperty cannot have multiple values.
You can see this failing here: https://dotnetfiddle.net/mnvmOI
Why can't I add a JProperty in this situation?
using System;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
JObject test = JObject.Parse("{\"test\":123,\"deeper\":{\"another\":\"value\"}}");
test.SelectToken("deeper.another").AddAfterSelf(new JProperty("new name","new value"));
}
}
The reason that the exception is thrown is that SelectToken()
returns the property's JValue
not the JProperty
itself. Specifically, it returns a JValue
owned by the JProperty
with name "another"
. You can see this if you do:
Console.WriteLine("Result type: {0}; result parent type: {1}", result.GetType(), result.Parent.GetType());
Which results in
Result type: Newtonsoft.Json.Linq.JValue; result parent type: Newtonsoft.Json.Linq.JProperty
And if you further print the object types from the top of the JToken
hierarchy to the value returned by SelectToken()
, you will see the JValue
tokens contained inside the JProperty
tokens:
Depth: 0, Type: JObject
Depth: 1, Type: JProperty: deeper
Depth: 2, Type: JObject
Depth: 3, Type: JProperty: another
Depth: 4, Type: JValue: value
The Json.NET documentation also indicates that SelectToken()
returns the selected property's value:
string name = (string)o.SelectToken("Manufacturers[0].Name"); Console.WriteLine(name); // Acme Co
Since a JProperty
cannot have more than one value, when you try to add a JProperty
immediately after the value in the hierarchy, you are trying to add it as a child of its parent JProperty
, which throws the exception.
Instead, add it to parent's parent:
test.SelectToken("deeper.another").Parent.AddAfterSelf(new JProperty("new name","new value"));
Sample fiddle showing all of the above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With