JavaScriptSerializer - JSON serialization of enum as string

JavaScriptSerializer - JSON serialization of enum as string

技术背景

在开发中,常常需要将 C# 中的枚举类型序列化为 JSON 格式。默认情况下,JavaScriptSerializer 会将枚举序列化为其数值,而很多时候我们希望将其序列化为字符串表示。不同的序列化库提供了不同的方法来实现这一需求。

实现步骤

使用 Newtonsoft.Json

  1. 属性级别的配置
    在属性上使用 [JsonConverter(typeof(StringEnumConverter))] 特性:
1
2
3
4
5
6
7
8
9
10
11
12
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class Person
{
public int Age { get; set; }

[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
}

public enum Gender { Male, Female }
  1. 枚举类型级别的配置
    如果希望某个枚举类型总是被序列化为字符串,可以直接在枚举类型上使用该特性:
1
2
[JsonConverter(typeof(StringEnumConverter))]
enum Gender { Male, Female }
  1. 全局配置
    可以在 JsonSerializer 中添加转换器:
1
2
var serializer = new JsonSerializer();
serializer.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

或者在序列化时添加转换器:

1
2
3
4
string SerializedResponse = JsonConvert.SerializeObject(
objToSerialize,
new Newtonsoft.Json.Converters.StringEnumConverter()
);

使用 System.Text.Json

在 .NET Core 3 及以后版本,可以使用 System.Text.Json 中的 JsonStringEnumConverter

1
2
3
4
5
6
7
8
using System.Text.Json;
using System.Text.Json.Serialization;

var person = new Person();
var stringEnumConverter = new System.Text.Json.Serialization.JsonStringEnumConverter();
JsonSerializerOptions opts = new JsonSerializerOptions();
opts.Converters.Add(stringEnumConverter);
var json = JsonSerializer.Serialize<Person>(person, opts);

也可以在属性或枚举类型上使用特性:

1
2
3
4
5
6
7
using System.Text.Json.Serialization;

[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }

[JsonConverter(typeof(JsonStringEnumConverter))]
enum Gender { Male, Female }

核心代码

Newtonsoft.Json 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class Person
{
public int Age { get; set; }

[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
}

public enum Gender { Male, Female }

class Program
{
static void Main()
{
var person = new Person { Age = 30, Gender = Gender.Male };
string json = JsonConvert.SerializeObject(person);
Console.WriteLine(json);
}
}

System.Text.Json 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System.Text.Json;
using System.Text.Json.Serialization;

public class Person
{
public int Age { get; set; }

[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }
}

public enum Gender { Male, Female }

class Program
{
static void Main()
{
var person = new Person { Age = 30, Gender = Gender.Male };
var options = new JsonSerializerOptions
{
Converters = { new JsonStringEnumConverter() }
};
string json = JsonSerializer.Serialize(person, options);
Console.WriteLine(json);
}
}

最佳实践

  • 统一配置:如果项目中大部分枚举都需要序列化为字符串,可以考虑全局配置转换器,避免在每个属性或枚举类型上重复添加特性。
  • 使用自定义转换器:对于有特殊需求的枚举序列化,如支持 Description 特性,可以自定义转换器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class CustomStringEnumConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type type = value.GetType() as Type;

if (!type.IsEnum) throw new InvalidOperationException("Only type Enum is supported");
foreach (var field in type.GetFields())
{
if (field.Name == value.ToString())
{
var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
writer.WriteValue(attribute != null ? attribute.Description : field.Name);

return;
}
}

throw new ArgumentException("Enum not found");
}
}

常见问题

  • 枚举值不存在:当反序列化时,如果 JSON 中的枚举值在枚举类型中不存在,StringEnumConverter 会抛出异常。可以使用自定义的 SafeEnumConverter 来处理这种情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class SafeEnumConverter : StringEnumConverter
{
private readonly int _defaultValue;

public SafeEnumConverter()
{
_defaultValue = -1;
}

public SafeEnumConverter(int defaultValue)
{
_defaultValue = defaultValue;
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
return base.ReadJson(reader, objectType, existingValue, serializer);
}
catch
{
return Enum.Parse(objectType, $"{_defaultValue}");
}
}

public override bool CanConvert(Type objectType)
{
return base.CanConvert(objectType) && objectType.GetTypeInfo().IsEnum;
}
}
  • 大小写问题:在使用 System.Text.Json 时,枚举序列化的大小写默认是敏感的。可以通过配置 JsonStringEnumConverter 的参数来调整大小写处理。

JavaScriptSerializer - JSON serialization of enum as string
https://119291.xyz/posts/javascriptserializer-json-serialization-of-enum-as-string/
作者
ww
发布于
2025年6月30日
许可协议