且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

收到错误消息“无法从Newtonsoft.Json.Linq.JProperty添加或删除项目".在Json.net

更新时间:2023-01-17 22:33:55

假设ValuesList<MyObject>,而您的MyObject类如下所示:

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>>();

之所以可行,是因为Json.Net默认情况下会忽略缺少的属性.由于MyObject类不包含要反序列化为的_id属性,因此您无需跳过试图将其从JSON中删除的箍.

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.

Remove()无效的原因的说明

Explanation of why Remove() didn't work

JToken.Remove()从其父级中删除JToken.从其父JObject中删除JProperty或从JArray中删除子JToken是合法的.但是,您不能从JProperty中删除该值. JProperty必须始终仅具有一个值.

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.

当您要求token["_id"]时,您会得到称为_idJProperty,而不是JProperty本身.因此,如果您尝试在该值上调用Remove(),则会收到错误消息.要使其按照您的方式工作,您需要像这样使用Parent:

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();

这说:找到名称为_id的属性并给我值.如果存在,请获取该值的父级(该属性),并将其从其父级(包含JObject)中删除."

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)."

一种更直接的方法是使用Property()方法直接访问该属性.但是,此方法仅在JObject上可用,而在JToken上不可用,因此您需要将inner的声明更改为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();
    ...
}

最后,如注释中所述,如果您使用的是C#6或更高版本,则可以使用空条件运算符将代码缩短一点:

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();