【问题标题】:Ignoring JSON enum value that doesn't exist in target model class during deserialization [duplicate]在反序列化期间忽略目标模型类中不存在的 JSON 枚举值 [重复]
【发布时间】:2017-11-15 14:51:33
【问题描述】:

所以我正在使用 C# 开发 API 包装器,我使用 Newtonsoft.Json 库将 JSON 数据反序列化为响应模型类。在响应模型类中,我有一个子项列表,每个子项都包含一个子项列表。这些是这样定义的:

public List<StatModel> Stats { get; set; }

每个 StatModel 都有一个基本上等于名称的属性:

public Stat Stat { get; set; }

这些是自动反序列化的,因为每个 Stat 都在这样的枚举中定义:

[EnumMember(Value = "Avg Walk Distance")]
AverageWalkDistance,

现在的问题是,如果实际 API 发生变化,包装器将不起作用,因为它没有指定 Stat 的定义。所以这意味着如果他们向 API 添加一个新的 Stat,包装器将无法工作,直到我手动添加它的定义,就像上面的代码块一样。

所以问题是,我怎样才能忽略没有相应 Stat 属性可用的值,或者我可以以某种方式重新设计整个事情,这样就不会发生这种情况?我猜我必须自己定义所有新值。

这是 GitHub 上的项目,可以更好地理解我的真正意思:https://github.com/eklypss/PUBGSharp

请求者进行反序列化并返回一个 StatResponse,其中包含一个名为 StatsRoot 的子项列表,每个子项都有自己的 StatModel 列表,这些 StatModel 是导致此问题的实际 stat 对象。每种类型的 Stat 都在 Enum/Stat.cs 文件中定义。

【问题讨论】:

  • 你使用什么 JSON 库来反序列化? JSON.Net 会忽略我认为你没有的属性。
  • 是的,我正在使用 Newtonsoft 的 Json.NET。上面的问题确实差不多,不知道除了写一个自定义的 JsonConverter 是否还有其他的解决方案。
  • 如果您不想创建自己的转换器,您可以使用exception handling

标签: c# json serialization json.net deserialization


【解决方案1】:

参考下面的问题,这个人和你有同样的问题。

How can I ignore unknown enum values during json deserialization?

然而,

即使您设法忽略了新的Stats,这对您的包装器也不利,因为包装器的消费者需要等待您添加新的Enum

所以,

如果我是你,我会考虑将 StatEnum 更改为 string,所以每当新的 Stat 出现时,您既不需要更改任何内容,也不需要更改 包装器的消费者 em>,不用等了。

【讨论】:

  • 我正在考虑这样的事情,但这种方法的问题是使用包装器的人必须知道特定统计数据的名称,而不仅仅是使用预先定义的值在枚举中定义。所以Stats.Find(x =&gt; x.Stat == "Headshot Kills") 而不仅仅是(x =&gt; x.Stat == Stat.HeadshotKills)
【解决方案2】:

如果您不想创建自己的容忍版本的StringEnumConverter,可以使用Json.NET 的exception handling 功能:

public class StatModel
{
    const string StatName = "label";

    [JsonProperty(StatName)]
    [JsonConverter(typeof(StringEnumConverter))]
    public Stat Stat { get; set; }

    public string Value { get; set; }
    public int? Rank { get; set; }
    public double? Percentile { get; set; }

    [OnError]
    void OnError(StreamingContext context, ErrorContext errorContext)
    {
        if (errorContext.OriginalObject == this && StatName.Equals(errorContext.Member))
        {
            errorContext.Handled = true;
        }
    }
}

当反序列化StatModel 或其任何嵌套对象时抛出异常时,将调用其OnError() 方法来处理错误。该方法检查是否抛出异常

  1. 在反序列化此特定对象时,并且
  2. 在反序列化“label”成员时。

如果是这样,异常被吞没。您还可以借此机会在模型中设置一个标志,指示 Stat 属性无效。

【讨论】:

    【解决方案3】:

    您可以让json.net 忽略缺失的成员。

    var settings = new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore,
        MissingMemberHandling = MissingMemberHandling.Ignore
    };
    
    var json = JsonConvert.DeserializeObject<MyClass>(jsonStr, settings);
    

    【讨论】:

    • 我之前确实试过这个。由于某种原因,它根本没有任何效果,如果缺少某些东西,它仍然会抛出相同的异常。
    • MissingMemberHandling 在 JSON 包含不是对象成员的属性 时抑制异常。它不会抑制无效 values 的异常,这就是这里发生的情况。
    猜你喜欢
    • 1970-01-01
    • 2020-04-02
    • 2017-04-10
    • 1970-01-01
    • 2013-08-17
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多