在将 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