Getting the error "Cannot add or remove items from Newtonsoft.Json.Linq.JProperty" in Json.net
Assuming Values
is a List<MyObject>
and your MyObject
class looks like this:
class MyObject
{
public string Time { get; set; }
public int Level { get; set; }
}
you can replace all that code with the following to get the result you want:
string json = File.ReadAllText(fileName);
Values = JToken.Parse(json)["docs"].ToObject<List<MyObject>>();
This works because Json.Net will ignore missing properties by default. Since the MyObject
class does not contain an _id
property to deserialize into, you don't need to jump through hoops trying to remove it from the JSON.
Explanation of why Remove()
didn't work
JToken.Remove()
removes a JToken
from its parent. It is legal to remove a JProperty
from its parent JObject
, or to remove a child JToken
from a JArray
. However, you cannot remove the value from a JProperty
. A JProperty
must always have exactly one value.
When you ask for token["_id"]
you get back the value of the JProperty
called _id
, not the JProperty
itself. Therefore you will get an error if you try to call Remove()
on that value. To make it work the way you are doing, you'd need to use Parent
like this:
if (inner["_id"] != null)
inner["_id"].Parent.Remove();
This says "Find the property whose name is _id
and give me the value. If it exists, get that value's parent (the property), and remove it from its parent (the containing JObject
)."
A more straightforward way to do it is to use the Property()
method to access the property directly. However, this method is only available on JObject
, not JToken
, so you would either need to change the declaration of inner
to a JObject
or cast it:
foreach (JObject inner in token["docs"].Children<JObject>())
{
JProperty idProp = inner.Property("_id");
if (idProp != null)
idProp.Remove();
...
}
Lastly, as mentioned in the comments, if you're using C# 6 or later you can shorten the code a bit using the null-conditional operator:
inner.Property("_id")?.Remove();