因此,我试图控制反序列化,方法是将json对象作为JObject读取,删除一些字段,然后使用Json.Net将其再次反序列化到我的目标对象.问题是,每当我try 删除字段时,都会收到错误消息:

An unhandled exception of type 'Newtonsoft.Json.JsonException' occurred in Newtonsoft.Json.dll

附加信息:无法在其中添加或删除项目 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)));
}

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"
        }
    ]
}

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.

推荐答案

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>>();

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.

Explanation of why 100 didn't work

JToken.Remove()从其父对象中删除JToken.将JProperty从其父JObject中移除是合法的,或者说从JArray中移除子代JToken是合法的.但是,您不能从JProperty中删除该值.JProperty必须始终只有一个值.

当你要token["_id"]的时候,你得到的是JProperty中的value,叫做_id,而不是JProperty本身.因此,如果你try 调用Remove(),你会得到一个错误.要使其按您目前的方式工作,您需要使用Parent,如下所示:

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

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)."

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();
    ...
}

最后,如 comments 中所述,如果使用C#6或更高版本,可以使用null条件运算符将代码缩短一点:

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

Json相关问答推荐

ArcGIS json到Geojson的变换

jq:将一个数组与多个数组连接起来

交换键和数组值,将旧键转换为新数组值,使用 jq

震动范围改善

Jolt - 如何比较 if else 条件的两个值

如何使用SQLite Trigger将JSON对象数组转换为新记录?

将带有::text[]的JSON数组转换未按预期工作

具有 (RegEx) 模式的 json-schema 中的枚举

使用 serde 和 csv crates 将嵌套的 json 对象序列化为 csv

在 JOLT 中重新排列值

Powershell 无法从名为 count 的键中获取价值

如何用 Xidel 正确读取这个 JSON 文件?

C# 合并 2 个几乎相同的 JSON 对象

如何获取json格式的KendoGrid显示数据?

Django - 异常处理最佳实践和发送自定义错误消息

Java JSON 序列化 - 最佳实践

Spring MVC控制器中的JSON参数

如何在dart Flutter 中将json字符串转换为json对象?

如何使用 SwiftyJSON 遍历 JSON?

添加json文件注释