收到错误消息“无法从Newtonsoft.Json.Linq.JProperty添加或删除项目".在Json.net [英] Getting the error "Cannot add or remove items from Newtonsoft.Json.Linq.JProperty" in Json.net
问题描述
因此,我尝试通过将json对象读取为JObject,删除一些字段,然后使用
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>
,而您的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
的值,而不是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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!