所以我试图通过将 json 对象作为 JObject 读取,删除一些字段,然后使用 Json.Net.问题是,每当我尝试删除字段时,都会收到错误消息:
So I'm trying to control deserialization by reading a json object as a JObject, deleting some fields, and then deserializing it again to my target object using Json.Net. The problem is, any time I try to delete a field, I get the error:
Newtonsoft.Json.JsonException"类型的未处理异常发生在 Newtonsoft.Json.dll
An unhandled exception of type 'Newtonsoft.Json.JsonException' occurred in Newtonsoft.Json.dll
附加信息:无法添加或删除项目Newtonsoft.Json.Linq.JProperty.
Additional information: Cannot add or remove items from Newtonsoft.Json.Linq.JProperty.
这是我的(简化,但仍然导致错误)代码:
Here's my (simplified, but still causing the error) code:
JToken token = (JToken)JsonConvert.DeserializeObject(File.ReadAllText(fileName));
foreach (JToken inner in token["docs"])
{
if (inner["_id"] != null)
inner["_id"].Remove();
MyObject read = new MyObject();
JsonConvert.PopulateObject(inner.ToString(), read);
Values.Add((MyObject)JsonConvert.DeserializeObject(inner.ToString(), typeof(MyObject)));
}
json 是一个非常大的文件,其中 docs 数组包含许多元素,如下所示(为清楚起见再次简化):
The json is a very large file where the docs array contains many elements as follows (again simplified for clarity):
{
"docs": [
{
"Time": "None",
"Level": 1,
"_id": "10208"
},
{
"Time": "None",
"Level": 1,
"_id": "10209"
}
]
}
或者,如果有更好的方法将 JSON 反序列化为特定类型,但仍然忽略其他字段,那将是一个不错的选择.
Alternatively if there's a better way to deserialize JSON to a specific type, but still ignoring additional fields, that would be a fine alternative.
假设 Values
是一个 List
和你的 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"]
时,您会返回名为 _id
的 JProperty
的 value>,而不是 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();
这篇关于收到错误“无法从 Newtonsoft.Json.Linq.JProperty 添加或删除项目"在 Json.net 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!