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

C#使用JSON.Net序列化Enum为含名称与数值键值对的实现问询

实现方案

步骤1:自定义枚举序列化转换器

继承Newtonsoft.Json的JsonConverter类,实现自定义序列化逻辑:

using Newtonsoft.Json;
using System;

public class EnumToNameValueConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // 只处理枚举类型
        return objectType.IsEnum;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        Enum enumValue = (Enum)value;
        writer.WriteStartObject();
        writer.WritePropertyName("name");
        writer.WriteValue(enumValue.ToString());
        writer.WritePropertyName("value");
        writer.WriteValue(Convert.ToInt32(enumValue));
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // 如果不需要反序列化可以直接抛NotImplementedException,下面是基础反序列化实现
        if (reader.TokenType == JsonToken.Null)
        {
            return null;
        }

        if (reader.TokenType == JsonToken.Integer)
        {
            return Enum.ToObject(objectType, reader.Value);
        }

        if (reader.TokenType == JsonToken.String)
        {
            return Enum.Parse(objectType, reader.Value.ToString());
        }

        // 处理自定义的{name,value}结构反序列化
        if (reader.TokenType == JsonToken.StartObject)
        {
            int value = 0;
            string name = null;
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    string propName = reader.Value.ToString();
                    reader.Read();
                    if (propName.Equals("value", StringComparison.OrdinalIgnoreCase))
                    {
                        value = Convert.ToInt32(reader.Value);
                    }
                    else if (propName.Equals("name", StringComparison.OrdinalIgnoreCase))
                    {
                        name = reader.Value.ToString();
                    }
                }
                else if (reader.TokenType == JsonToken.EndObject)
                {
                    break;
                }
            }
            // 优先用数值反序列化,避免字符串拼写问题
            return Enum.ToObject(objectType, value);
        }

        throw new JsonSerializationException("无法解析枚举类型");
    }
}

步骤2:使用转换器

有两种使用方式,按需选择即可:

方式1:指定单个属性使用转换器

给枚举类型的属性添加JsonConverter特性,仅对标记的属性生效:

public class Product
{
    [JsonConverter(typeof(EnumToNameValueConverter))]
    public DisplayStatus displayStatus { get; set; }
    
    [JsonConverter(typeof(EnumToNameValueConverter))]
    public DrugClass drugClass { get; set; }
    
    [JsonConverter(typeof(EnumToNameValueConverter))]
    public DrugType drugType { get; set; }
}

序列化逻辑保持原有写法即可:

string JSONOutput = JsonConvert.SerializeObject(product);

方式2:全局注册转换器,所有枚举都按此规则序列化

序列化时传入转换器参数,不需要给每个属性单独加特性:

string JSONOutput = JsonConvert.SerializeObject(product, new EnumToNameValueConverter());

说明

  • 如果枚举是Flags特性标记的位域枚举,name字段会自动返回多个枚举值用逗号分隔的拼接字符串,符合常规使用习惯
  • 若不需要反序列化能力,可以删掉ReadJson方法的实现,直接抛出NotImplementedException即可减少冗余代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:12:02