Skip to content

枚举型(enum)字段的序列化

Java

默认情况下枚举字段会序列为字符型,值为枚举字段的名字(即 Enum<E extends Enum<E>>name() 方法的返回值)。

jackson 中可以通过设置 SerializationFeature.WRITE_ENUMS_USING_TO_STRINGSerializationFeature.WRITE_ENUMS_USING_INDEX 来改变默认的枚举型序列化结果。默认情况下这两个设置均为 false,可以通过如下方式设置:

java
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
mapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, true);
return mapper.writeValueAsString(obj);

WRITE_ENUMS_USING_TO_STRING 设置为 true , 将序列化为 Enum.toString() 的返回值。而 Enum.toString() 方法可以重写。

WRITE_ENUMS_USING_INDEX 设置为 true 则序列化为 Enum.ordinal() 的返回值(及该枚举值的索引),这时值是 Integer 型。另外 Enum.ordinal() 不可以重写。

两个同时设置为 true 时, WRITE_ENUMS_USING_INDEX 拥有较高的优先级。

java
/**
 * Feature that determines standard serialization mechanism used for
 * Enum values: if enabled, return value of <code>Enum.toString()</code>
 * is used; if disabled, return value of <code>Enum.name()</code> is used.
 *<p>
 * Note: this feature should usually have same value
 * as {@link DeserializationFeature#READ_ENUMS_USING_TO_STRING}.
 *<p>
 * Feature is disabled by default.
 */
WRITE_ENUMS_USING_TO_STRING(false),

/**
 * Feature that determines whethere Java Enum values are serialized
 * as numbers (true), or textual values (false). If textual values are
 * used, other settings are also considered.
 * If this feature is enabled,
 *  return value of <code>Enum.ordinal()</code>
 * (an integer) will be used as the serialization.
 *<p>
 * Note that this feature has precedence over {@link #WRITE_ENUMS_USING_TO_STRING},
 * which is only considered if this feature is set to false.
 *<p>
 * Feature is disabled by default.
 */
WRITE_ENUMS_USING_INDEX(false),

下为一个 enum 型的示例:

java
public enum LogLevel {
    /**
     * 异常
     */
    Error("Error", 1),
    /**
     * 警告
     */
    Warn("Warn", 2),
    /**
     * 消息
     */
    Info("Info", 3),
    /**
     * 调试
     */
    Debug("Debug", 4),
    /**
     * 跟踪
     */
    Trace("Trace", 5);

    private String name;
    private int index;

    LogLevel(String name, int index) {
        this.name = name;
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public LogLevel valueOf(int value) {
        switch (value) {
            case 1:
                return LogLevel.Error;
            case 2:
                return LogLevel.Warn;
            case 3:
                return LogLevel.Info;
            case 4:
                return LogLevel.Debug;
            case 5:
                return LogLevel.Trace;
            default:
                return LogLevel.Info;
        }
    }

//    // Error: java: LogLevel 中的 ordinal() 无法覆盖 java.lang.Enum 中的 ordinal()
//    @Override
//    public int ordinal() {
//        return this.index;
//    }

    @Override
    public String toString() {
        return String.valueOf(this.index);
    }
}

C#

C# 中默认序列化为对应的整形值。如果需要序列化为字符串则需要使用 JsonConverter 特性。

csharp
/// <summary>
/// 日志级别
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public LogLevel Level { get; set; } = LogLevel.Info;

保持 Java & C# 中序列化结果一致

Java 和 C# 中枚举型最大的不同就是:Java 中不能指定索引值,只能从零开始;C# 中默认也是从零开始,但是可以手动指定每个的索引值。

统一序列化成数字

虽然 Java 中 将 WRITE_ENUMS_USING_TO_STRING 设置为 true,然后再重写 ToString 方法可以将其序列化成指定的索引值,但其类型是 String,而不是 C# 中默认的整形。

统一序列化成名字(推荐)

在 C# 中将其序列化为字符串,这样就可以和 Java 中的默认方法一致了。

参考

  1. Java enum 的用法详解
  2. Newtonsoft.Json 序列化 Enum 类型

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.