所以我试图通过将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反序列化为特定类型,但仍然忽略其他字段,那么这将是一个很好的选择。
假设Values
是List<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"]
时,您会得到名为_id
的JProperty
的值,而不是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();