JSON反序列化为C#对象前校验属性值,解决None值转换报错问题
解决方案
方案1:全局配置JsonSerializerSettings(推荐)
一次性处理所有反序列化场景,无需提前对JSON字符串做替换操作:
首先自定义通用转换器处理None值,自动返回对应类型默认值:
public class NoneToDefaultConverter : JsonConverter { public override bool CanConvert(Type objectType) => true; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 匹配None或null值 if (reader.Value?.ToString() == "None" || reader.TokenType == JsonToken.Null) { // 值类型返回默认值,引用类型返回null return objectType.IsValueType ? Activator.CreateInstance(objectType) : null; } // 兼容处理日期、数值类型的格式转换 try { return Convert.ChangeType(reader.Value, objectType); } catch { return objectType.IsValueType ? Activator.CreateInstance(objectType) : null; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 仅需反序列化可直接抛出未实现异常 throw new NotImplementedException(); } }
然后配置全局序列化设置:
var settings = new JsonSerializerSettings { // 自动填充默认值 DefaultValueHandling = DefaultValueHandling.Populate, // 注册自定义转换器 Converters = { new NoneToDefaultConverter() } }; // 直接反序列化即可,无需提前替换None var quote = JsonConvert.DeserializeObject<Quote>(json, settings);
方案2:自定义属性单独配置字段
如果不需要全局生效,仅需要针对指定类的特定字段做处理,可以用泛型转换器加特性标记的方式实现:
首先定义泛型转换器:
public class NoneToDefaultConverter<T> : JsonConverter<T> { public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value?.ToString() == "None" || reader.TokenType == JsonToken.Null) { return default(T); } try { return (T)Convert.ChangeType(reader.Value, typeof(T)); } catch { return default(T); } } public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer) { throw new NotImplementedException(); } }
给需要处理的属性加上JsonConverter特性即可:
public class Quote { [JsonConverter(typeof(NoneToDefaultConverter<string>))] public string category { get; set; } [JsonConverter(typeof(NoneToDefaultConverter<DateTime>))] public DateTime date { get; set; } [JsonConverter(typeof(NoneToDefaultConverter<decimal>))] public decimal amount { get; set; } }
自定义默认值补充
如果不需要使用系统默认值(比如DateTime默认是0001/1/1),可以配合DefaultValue特性自定义默认值,只需要在全局设置中开启DefaultValueHandling.Populate即可:
public class Quote { public string category { get; set; } [DefaultValue(typeof(DateTime), "2023-01-01 00:00:00")] public DateTime date { get; set; } [DefaultValue(typeof(decimal), "0.01")] public decimal amount { get; set; } }
内容的提问来源于stack exchange,提问作者j4rey
相关产品推荐
相关产品推荐

