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

标签 c# json serialization json.net

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

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

Additional information: Cannot add or remove items from 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()没用

JToken.Remove()删除 JToken从它的 parent 那里。删除 JProperty 是合法的来自其父 JObject , 或删除子 JToken来自 JArray .但是,您不能从 JProperty 中删除该值。 .一个 JProperty必须始终只有一个值。

当您要求 token["_id"]你得到了JProperty调用_id ,而不是 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 或更高版本,您可以使用空条件运算符稍微缩短代码:

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

关于c# - 在 Json.net 中获取错误 "Cannot add or remove items from Newtonsoft.Json.Linq.JProperty",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21898727/

相关文章:

json - 在Dart中无法高精度地解析DateTime

Wcf、序列化、只读成员

c# - WPF - ListView 的 ItemsSource 中的绑定(bind)不能是列表

c# - 在 Windows 应用程序中,如何使用 C#.Net 2.0 在图片框中保存来自网络摄像头的实时图像

jquery - 在 HTML 中编写 JSON

python - Pandas:将 JSON 列表值拆分为新列

java - SpringFramework ResponseBody 返回具有空值的对象

java - Jackson ObjectMapper 将值读取到特定的 Java 对象中

c# - 在单点触控中将 24 位图像转换为 8 位?

c# - 可以将 DLL 合并到 .NET EXE 中吗?