.NET 7中如何正确处理JSON反序列化中空字符串与对象混合的问题?
解决ASP.NET Core Web API中空字符串转null/默认值的JSON解析问题
问题背景
升级ASP.NET Core Web API时,遇到调用方将空对象/值以""(空字符串)形式发送的情况,且对方不修改格式。例如:
{ "user": "", "subscription": { "id": 123456789, "origin": "", "verlenging": true }, "voucher": { "name": "", "id": 0 }, "webLinkId": "" }
当user字段是正常对象、webLinkId是数值时也需要正常解析,目前报错:
The JSON value could not be converted to ...
以下是可行的解决办法:
1. 自定义JSON转换器处理引用类型(如User对象)
针对引用类型,将空字符串转换为null,正常对象则正常反序列化:
public class EmptyStringToNullConverter<T> : JsonConverter<T> where T : class { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String && string.IsNullOrEmpty(reader.GetString())) { return null; } return JsonSerializer.Deserialize<T>(ref reader, options); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, options); } }
2. 自定义转换器处理值类型(如int、DateTime)
非可空int(空字符串转0)
public class EmptyStringToDefaultIntConverter : JsonConverter<int> { public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { var str = reader.GetString(); if (string.IsNullOrEmpty(str)) return 0; return int.TryParse(str, out var result) ? result : throw new JsonException("无法转换为int类型"); } else if (reader.TokenType == JsonTokenType.Number) { return reader.GetInt32(); } throw new JsonException("无法将JSON值转换为int类型"); } public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) { writer.WriteNumberValue(value); } }
可空DateTime(空字符串转null)
public class EmptyStringToNullableDateTimeConverter : JsonConverter<DateTime?> { public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { var str = reader.GetString(); if (string.IsNullOrEmpty(str)) return null; return DateTime.TryParse(str, out var result) ? result : null; } else if (reader.TokenType == JsonTokenType.String) { return reader.GetDateTime(); } return null; } public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) { if (value.HasValue) writer.WriteStringValue(value.Value); else writer.WriteNullValue(); } }
3. 应用转换器
方式一:单个模型属性标记
在请求模型的目标属性上添加转换器特性:
public class RequestModel { [JsonConverter(typeof(EmptyStringToNullConverter<User>))] public User User { get; set; } public Subscription Subscription { get; set; } public Voucher Voucher { get; set; } [JsonConverter(typeof(EmptyStringToDefaultIntConverter))] public int WebLinkId { get; set; } } public class User { public bool IsDomi { get; set; } public bool IsStudent { get; set; } // 其他属性... [JsonConverter(typeof(EmptyStringToNullableDateTimeConverter))] public DateTime? Birthday { get; set; } }
方式二:全局注册(所有模型生效)
在Program.cs中配置全局JSON序列化选项:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new EmptyStringToNullConverter<User>()); options.JsonSerializerOptions.Converters.Add(new EmptyStringToDefaultIntConverter()); options.JsonSerializerOptions.Converters.Add(new EmptyStringToNullableDateTimeConverter()); });
注意事项
- 根据实际需求扩展转换器,比如枚举、decimal等类型的处理;
- 测试边界场景:空字符串、正常数值、正常对象、null值等;
- 若使用Newtonsoft.Json而非System.Text.Json,只需调整转换器继承的基类为Newtonsoft的对应类型。
内容的提问来源于stack exchange,提问作者ItsProbablySomethingStupid
相关产品推荐
相关产品推荐

