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

如何用System.Text.Json自定义枚举JSON转换器适配后端枚举?

问题分析与解决方案

你的思路方向是对的——用自定义JSON转换器来做枚举和后端字符串的适配,避免修改现有枚举和UI代码,但当前的转换器实现有问题:你继承了JsonConverter<string>,但实际要处理的是枚举类型,而不是string,所以Write方法的参数类型不对,没法直接关联到枚举的Description特性。

正确的实现步骤

  1. 调整转换器基类:应该继承JsonConverter<T>(泛型,针对具体枚举)或者JsonConverter(非泛型,处理所有枚举),这样才能拿到枚举值来读取特性。
  2. 编写工具方法读取Description:通过反射获取枚举字段上的DescriptionAttribute值。
  3. 实现序列化/反序列化逻辑:序列化时把枚举转成Description字符串,反序列化时把后端字符串转回对应的枚举值。

完整代码示例

1. 通用枚举Description转换器(支持所有枚举)

using System.ComponentModel;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;

public class EnumDescriptionConverter : JsonConverter<Enum>
{
    // 获取枚举值的Description特性值
    private string GetEnumDescription(Enum enumValue)
    {
        var fieldInfo = enumValue.GetType().GetField(enumValue.ToString());
        var descriptionAttr = fieldInfo?.GetCustomAttribute<DescriptionAttribute>();
        return descriptionAttr?.Description ?? enumValue.ToString();
    }

    // 根据Description字符串找对应的枚举值
    private TEnum GetEnumFromDescription<TEnum>(string description) where TEnum : Enum
    {
        foreach (var field in typeof(TEnum).GetFields())
        {
            if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr && attr.Description == description)
            {
                return (TEnum)field.GetValue(null);
            }
        }
        // 找不到的话 fallback 到按名称解析,或者抛异常
        return Enum.Parse<TEnum>(description);
    }

    public override Enum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var description = reader.GetString();
        return GetEnumFromDescription<Enum>(description);
    }

    public override void Write(Utf8JsonWriter writer, Enum value, JsonSerializerOptions options)
    {
        var description = GetEnumDescription(value);
        writer.WriteStringValue(description);
    }
}

2. 针对特定枚举的转换器(如果只需要处理RenovationMode)

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

public class RenovationModeConverter : JsonConverter<RenovationMode>
{
    private string GetDescription(RenovationMode mode)
    {
        return mode switch
        {
            RenovationMode.RoofTruss => "Beams",
            RenovationMode.RoofTiles => "Slats",
            RenovationMode.CompleteRoofStructureReplacement => "RoofStructure",
            RenovationMode.Waterproofing => "Waterproofing",
            _ => mode.ToString()
        };
    }

    private RenovationMode GetModeFromDescription(string description)
    {
        return description switch
        {
            "Beams" => RenovationMode.RoofTruss,
            "Slats" => RenovationMode.RoofTiles,
            "RoofStructure" => RenovationMode.CompleteRoofStructureReplacement,
            "Waterproofing" => RenovationMode.Waterproofing,
            _ => Enum.Parse<RenovationMode>(description)
        };
    }

    public override RenovationMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var description = reader.GetString();
        return GetModeFromDescription(description);
    }

    public override void Write(Utf8JsonWriter writer, RenovationMode value, JsonSerializerOptions options)
    {
        var description = GetDescription(value);
        writer.WriteStringValue(description);
    }
}

使用方式

在序列化时配置转换器:

var options = new JsonSerializerOptions();
// 通用转换器,支持所有枚举
options.Converters.Add(new EnumDescriptionConverter());
// 或者针对特定枚举的转换器
// options.Converters.Add(new RenovationModeConverter());

var mode = RenovationMode.RoofTruss;
var json = JsonSerializer.Serialize(mode, options);
// 输出结果:"Beams"

总结

你的核心思路是对的,但转换器的基类选错了,改成处理枚举类型的转换器后,就能通过反射或者switch读取Description特性,完成前后端的适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:10:11