在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反序列化为特定类型,但仍然忽略其他字段,那将是一个很好的选择。

假设ValuesList ,您的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中删除子JTokenJArray 。 但是,您无法从JProperty删除该值。 JProperty必须始终只有一个值。

当你要求token["_id"]你会JProperty名为_idJProperty ,而不是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();