在 Json.net 中获取错误"Cannot add or remove items from Newtonsoft.Json.Linq.JProperty"



所以我试图通过将json对象读取为JObject来控制反序列化,删除一些字段,然后使用json.Net将其再次反序列化到我的目标对象。问题是,每当我试图删除字段时,我都会收到错误:

类型为"Newtonsoft.Json.JsonException"的未处理异常发生在Newtonsoft.Json.dll 中

附加信息:无法从中添加或删除项目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>,并且您的MyObject类如下所示:

class MyObject
{
public string Time { get; set; }
public int Level { get; set; }
}

您可以用以下代码替换所有代码以获得您想要的结果:

string json = File.ReadAllText(fileName);
Values = JToken.Parse(json)["docs"].ToObject<List<MyObject>>();

这是因为Json.Net默认情况下会忽略缺少的属性。由于MyObject类不包含要反序列化到的_id属性,因此不需要费力地将其从JSON中删除。

Remove()不工作的原因解释

CCD_ 7将CCD_。从父JObject中删除JProperty或从JArray中删除子JToken是合法的。但是,不能从JProperty中删除该值。JProperty必须始终只有一个值。

当您请求token["_id"]时,您会得到名为_idJProperty,而不是JProperty本身。因此,如果尝试对该值调用Remove(),则会出现错误。为了让它按你现在的方式工作,你需要像这样使用Parent

if (inner["_id"] != null)
inner["_id"].Parent.Remove();

上面写着"找到名称为_id的属性并给我值。如果它存在,获取该值的父级(属性),并将其从其父级(包含JObject的)中删除。">

更直接的方法是使用Property()方法直接访问属性。但是,此方法仅在JObject上可用,而在JToken上不可用,因此您需要将inner的声明更改为JObject或强制转换它:

foreach (JObject inner in token["docs"].Children<JObject>())
{
JProperty idProp = inner.Property("_id");
if (idProp != null)
idProp.Remove();
...
}

最后,正如评论中所提到的,如果你使用的是C#6或更高版本,你可以使用null条件运算符来缩短代码:

inner.Property("_id")?.Remove();

根据Brian的精彩回答,您可以在您的情况下简单地这样做:

var inner_id = inner["_id"] as JProperty;
if (inner_id != null)
inner_id.Remove();

相关内容

  • 没有找到相关文章

最新更新