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

C#如何将null属性序列化为Python兼容的None?

问题描述

需要将C#对象序列化为JSON传递给Python脚本,要求C#中值为null的属性在JSON里显示为None以适配Python。自定义了NullJsonConverter但转换器仅在属性有值时触发,null值场景下完全不生效。

给出的转换器代码:

public class NullJsonConverter : JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var jsonString = reader.GetString();

        if (!string.IsNullOrEmpty(jsonString))
        {
            return JsonSerializer.Deserialize<string>(jsonString, options);
        }

        return null;
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        if (value == null)
        {
            //Logic to convert from null to None
        }

        JsonSerializer.Serialize(writer, value);
    }
}

序列化配置:

return new JsonSerializerOptions()
{
    DefaultIgnoreCondition = JsonIgnoreCondition.Never,
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters =
    {
        new JsonStringEnumConverter(),
        new NullJsonConverter()
    }
};

问题原因与解决方法

核心问题

  1. null值不触发类型转换器:System.Text.Json在处理属性值为null时,会直接生成null JSON值,不会调用针对具体值类型(如string)的转换器。
  2. 转换器覆盖范围有限:你写的NullJsonConverter仅针对string类型,无法处理int?、float?等其他可空值类型。

解决步骤

1. 编写通用可空类型转换器

使用JsonConverterFactory实现批量处理所有可空类型的转换器,覆盖string、int?、float?等场景:

public class NullToNoneConverter : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert)
    {
        // 判断是否为可空类型(string本身是引用类型,Nullable<T>是值类型的可空包装)
        return typeToConvert == typeof(string) || 
               (typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Nullable<>));
    }

    public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
    {
        if (type == typeof(string))
        {
            return new NullToNoneStringConverter();
        }
        // 针对Nullable<T>类型,生成对应的转换器实例
        var underlyingType = Nullable.GetUnderlyingType(type);
        var converterType = typeof(NullToNoneValueConverter<>).MakeGenericType(underlyingType);
        return (JsonConverter)Activator.CreateInstance(converterType);
    }

    // string类型的具体转换逻辑
    private class NullToNoneStringConverter : JsonConverter<string>
    {
        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            // 反序列化时将"None"转为null
            if (reader.TokenType == JsonTokenType.String && reader.GetString() == "None")
            {
                return null;
            }
            return reader.GetString();
        }

        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
        {
            // 序列化时将null转为"None"
            if (value == null)
            {
                writer.WriteStringValue("None");
            }
            else
            {
                writer.WriteStringValue(value);
            }
        }
    }

    // 可空值类型(int?、float?等)的转换逻辑
    private class NullToNoneValueConverter<T> : JsonConverter<T?> where T : struct
    {
        public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String && reader.GetString() == "None")
            {
                return null;
            }
            return JsonSerializer.Deserialize<T>(ref reader, options);
        }

        public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options)
        {
            if (!value.HasValue)
            {
                writer.WriteStringValue("None");
            }
            else
            {
                JsonSerializer.Serialize(writer, value.Value, options);
            }
        }
    }
}

2. 更新序列化配置

将原来的NullJsonConverter替换为通用转换器:

return new JsonSerializerOptions()
{
    DefaultIgnoreCondition = JsonIgnoreCondition.Never,
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters =
    {
        new JsonStringEnumConverter(),
        new NullToNoneConverter()
    }
};

3. 关键说明

  • 保持DefaultIgnoreCondition = JsonIgnoreCondition.Never,确保null属性不会被序列化框架忽略,转换器才能处理到这些值。
  • 通用转换器会自动识别所有可空类型,序列化时将null转为"None",反序列化时将"None"转回null,完全适配Python的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:30:21