在Json.net中获取错误“无法在Newtonsoft.Json.Linq.JProperty中添加或删除项”
所以我试图通过将json对象作为JObject读取,删除一些字段,然后使用Json.Net将其再次反序列化为我的目标对象来控制反序列化 。 问题是,每次我尝试删除字段时,都会收到错误:
Newtonsoft.Json.dll中出现未处理的“Newtonsoft.Json.JsonException”类型exception
其他信息:无法添加或删除Newtonsoft.Json.Linq.JProperty中的项目。
这是我的(简化但仍然导致错误)代码:
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数组包含许多元素,如下所示(为简洁起见,再次简化):
{ "docs": [ { "Time": "None", "Level": 1, "_id": "10208" }, { "Time": "None", "Level": 1, "_id": "10209" } ] }
或者,如果有更好的方法将JSON反序列化为特定类型,但仍然忽略其他字段,那将是一个很好的选择。
假设Values
是List
,您的MyObject
类如下所示:
class MyObject { public string Time { get; set; } public int Level { get; set; } }
您可以使用以下代码替换所有代码以获得所需的结果:
string json = File.ReadAllText(fileName); Values = JToken.Parse(json)["docs"].ToObject>();
这是有效的,因为默认情况下Json.Net将忽略缺少的属性。 由于MyObject
类不包含要反序列化的_id
属性,因此您无需跳过尝试将其从JSON中删除的环。
解释为什么Remove()
不起作用
JToken.Remove()
从其父级中删除JToken
。 从其父JObject
中删除JObject
或从JObject
中删除子JToken
是JArray
。 但是,您无法从JProperty
删除该值。 JProperty
必须始终只有一个值。
当你要求token["_id"]
你会JProperty
名为_id
的JProperty
的值 ,而不是JProperty
本身。 因此,如果您尝试对该值调用Remove()
,则会出现错误。 为了使它按照您的方式工作,您需要这样做:
if (inner["_id"] != null) inner["_id"].Parent.Remove();
这说“找到名称为_id
的属性并给我值。如果存在,则获取该值的父(属性),并将其从其父(包含JObject
)中JObject
。”
另一种方法可能更明确一点就是这样说:
JProperty id = inner.Children().FirstOrDefault(p => p.Name == "_id"); if (id != null) id.Remove();
根据Brian的Brillian回答,你可以在你的情况下做到这一点:
var inner_id = inner["_id"] as JProperty; if (inner_id != null) inner_id.Remove();