You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# REST API接收JSON含null值时类型转换错误问题咨询

问题根因

报错的核心原因是System.Text.Json(或Newtonsoft.Json)反序列化阶段,遇到JSON中明确传入的null值时,会先进行类型匹配校验:如果目标属性为不可空值类型(如bool/int未加?),会直接抛出类型转换错误,根本不会走到属性的赋值、默认值触发逻辑;如果目标为可空类型,会直接将null赋值给属性,覆盖你声明的初始默认值。而JsonIgnore系列配置仅控制序列化输出的忽略规则,对反序列化阶段的null值处理无效。


解决方案

方案1:可修改外部实体类代码

直接给需要处理null值的属性加对应JsonConverter即可,无需修改原有逻辑:
首先实现通用Null转默认值Converter:

using System.Text.Json;
using System.Text.Json.Serialization;

public class NullToDefaultConverter<T> : JsonConverter<T>
{
    private readonly T _customDefault;

    // 无参构造用类型默认值
    public NullToDefaultConverter()
    {
        _customDefault = default;
    }

    // 支持传入自定义默认值
    public NullToDefaultConverter(T customDefault)
    {
        _customDefault = customDefault;
    }

    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.Null)
        {
            return _customDefault;
        }
        return JsonSerializer.Deserialize<T>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, value, options);
    }
}

然后给属性标记Converter即可:

public class MyClass
{
    // null时返回自定义默认值
    [JsonConverter(typeof(NullToDefaultConverter<string>), "default value")]
    public string Key {get;set;}

    // null时返回false
    [JsonConverter(typeof(NullToDefaultConverter<bool>), false)]
    public bool IsThing {get;set;}
}

这种方式不需要属性声明为可空,null值会在反序列化转换阶段就被替换为默认值,不会抛出转换错误。


方案2:完全无法修改外部实体类代码

直接在反序列化入口配置全局JsonConverter即可,不需要改动实体类:
先实现Converter工厂,自动适配所有需要处理的类型:

public class NullToDefaultConverterFactory : JsonConverterFactory
{
    // 自定义需要处理null转默认值的类型
    private static readonly Type[] HandleTypes = new[] { typeof(string), typeof(bool), typeof(int), typeof(DateTime) };

    public override bool CanConvert(Type typeToConvert)
    {
        return HandleTypes.Contains(typeToConvert) || 
               (Nullable.GetUnderlyingType(typeToConvert) != null && HandleTypes.Contains(Nullable.GetUnderlyingType(typeToConvert)));
    }

    public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
    {
        var actualType = Nullable.GetUnderlyingType(typeToConvert) ?? typeToConvert;
        var converter = Activator.CreateInstance(typeof(NullToDefaultConverter<>).MakeGenericType(actualType), 
            // 这里可以配置各类型的默认值
            actualType == typeof(string) ? "default value" : 
            actualType == typeof(bool) ? false : 
            Activator.CreateInstance(actualType));
        return (JsonConverter)converter;
    }
}

然后在你把JsonElement Payload反序列化为目标类型时,传入配置了该工厂的序列化选项:

var deserializeOptions = new JsonSerializerOptions
{
    Converters = { new NullToDefaultConverterFactory() }
};
var targetEntity = JsonSerializer.Deserialize(Payload.GetRawText(), targetType, deserializeOptions);

如果是ASP.NET Core项目,也可以全局注册该配置,所有接口反序列化自动生效:

// Program.cs
builder.Services.AddControllers()
    .AddJsonOptions(opt =>
    {
        opt.JsonSerializerOptions.Converters.Add(new NullToDefaultConverterFactory());
    });

原有方案失效原因

  • 可空属性加默认值:反序列化时JSON明确传入null,会直接覆盖属性的初始默认值
  • JsonIgnore配置:仅控制序列化输出逻辑,不影响反序列化阶段的赋值
  • 手写get/set:如果属性为不可空类型,反序列化时类型转换错误先触发,根本走不到set方法;如果是可空类型,你之前的写法理论上可以生效,前提是你没有在其他地方重置了字段值,或者你用的序列化器配置了跳过null值赋值的规则。

内容的提问来源于stack exchange,提问作者Jeff Patton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:21:03