在将 JSON 反序列化为 C# 对象之前检查属性值

Posted

技术标签:

【中文标题】在将 JSON 反序列化为 C# 对象之前检查属性值【英文标题】:check property values before deserializing JSON into C# Objects 【发布时间】:2022-01-09 04:45:23 【问题描述】:

我有以下 json 被第三方 api 返回


    'category':'Cat1',
    'date': '12-12-2021'
    'amount' 23.23

正在反序列化为以下 C# 类

public class Quote
    public string category get;set;
    public DateTime date get;set;
    public decimal amount get;set;

但有时我们会得到None 作为值,例如:


    'category': None,
    'date': None
    'amount' None

应用程序在反序列化时出错,实际上它在尝试序列化之前解析 json 时出错。

 JsonConvert.DeserializeObject<Quote>(json, settings);<--exception here

'Error parsing NaN value. Path 'category', line X, position XX.'

我们尝试使用json.Replace("None", "null");None 替换为null,但是当它尝试将日期和金额(分别为DateTime 和十进制类型)设置为null 时出现异常。

有没有办法检查传入的值,每当我们得到None 时,我们将属性设置为default(Type) 值,或者在JsonSerializerSettings 中全局设置,或者单独使用自定义属性?

【问题讨论】:

所以你实际上是在说你得到了无效的 JSON - 你的第一个例子实际上也是无效的 - 嗯,他们都是真的 第一个 JSON 很好......我没有复制粘贴实际的 json............问题是 None 相当于 C# @ 987654335@ 或 default(Type) 类型不能为 null 您可以查看自定义反序列化以检查“无”并将其设为空吗? newtonsoft.com/json/help/html/CustomJsonConverterGeneric.htm 【参考方案1】:

这实际上是关于验证 - 您应该在使用来自外部源的任何内容之前执行此操作。

这是无效的 JSON:


    'category':'Cat1',
    'date': '12-12-2021'
    'amount' 23.23



    'category': Done,
    'date': Done
    'amount' Done

应该是这个格式

双引号不是单引号 名称/值对之间不缺少“:” 除了最后一个之外,中间没有逗号,后面应该没有逗号

允许的示例:


    "category":'Cat1",
    "date": "12-12-2021",
    "amount": 23.23

允许的示例:


    "category": "None",
    "date": "None",
    "amount": "None"

您可以在 JSON 字符串中使用有效的空值对集:


    "category": null,
    "date": null,
    "amount": null

这是一个具有可为空值类型的示例 c# 类:

public class Quote

    public string category get;set;
    public DateTime? date get;set;
    public decimal? amount get;set;

现在至于实际验证以及用什么替换什么,这可能在接受值的方法上或在 Quote 的设置器中。我没有在这里重复大量代码,而是参考了其他问题的答案,因为这是一个架构和设计问题:

将验证放入 setter: C# add validation on a setter method

现在,如果您想在 setter 之前/之外进行验证,您可以执行以下非常粗略的大纲:如何处理异常取决于您。

public class TestQuote

    // these COULD be nullable types (see above) or some default
    public string Category  get; private set; 
    public DateTime? QuoteDate  get; private set; 
    public decimal? Amount  get; private set; 

    private NumberStyles style;

    public void SetCategory(string value)
    
         //... your logic, throw exception if validation failed
         Category = value;
    

    public void SetAmount(string value)
    
         //... your logic, throw exception if validation failed
         // Now how you parse and default value is up to you re:
         // https://docs.microsoft.com/en-us/dotnet/api/system.decimal.parse?view=net-6.0
         style = NumberStyles.Number | NumberStyles.AllowCurrencySymbol;
         Amount = Decimal.Parse(value, style, CultureInfo.InvariantCulture);
    
    
    public void SetQuoteDate(string value)
    
         //... your logic, throw exception if validation failed 
         // OR change to some default DateTime
         // HOW you parse this and what default is up to you ref:
         // https://docs.microsoft.com/en-us/dotnet/api/system.datetime.parse?view=net-6.0
         QuoteDate = DateTime.Parse(value);
    

现在如何调用它取决于您,因为您没有提供访问 JSON 源的方法。

【讨论】:

以上是关于在将 JSON 反序列化为 C# 对象之前检查属性值的主要内容,如果未能解决你的问题,请参考以下文章

将 JSON 反序列化为 C# 类,其中 JSON 中的属性名称是动态的

如何在将 xml 反序列化为 c# 对象时获取单个 xml 元素的多个值?

JavaScriptSerializer类 对象序列化为JSON,JSON反序列化为对象

将 JSON 反序列化为 C# 对象以在网格中将嵌套数组显示为字符串

在将 json 反序列化为对象时,使用 jackson 将 asp.net / MS 专有 json Dateformat 转换为 java8 LocalDateTime

将 JSON 字符串反序列化为多个 C# 对象