jackson对枚举的序列化和反序列化,是根据枚举名称还是枚举位置下标
这是一个很好的问题!Jackson对枚举的默认行为是:
默认行为
序列化:基于枚举的名称(name()),而不是下标(ordinal())
反序列化:基于枚举的名称进行匹配
示例说明
JAVA
public enum Status {
PENDING, // ordinal=0
APPROVED, // ordinal=1
REJECTED // ordinal=2
}
public class Order {
private Status status;
// getter/setter
}
序列化示例
JAVA
Order order = new Order();
order.setStatus(Status.APPROVED);
// 序列化结果为:{"status": "APPROVED"}
// 而不是 {"status": 1}
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(order);
反序列化示例
JAVA
String json = "{\"status\": \"APPROVED\"}";
Order order = mapper.readValue(json, Order.class);
// order.getStatus() = Status.APPROVED
如何改变默认行为
1. 使用下标(ordinal)进行序列化/反序列化
JAVA
public enum Status {
PENDING, // 0
APPROVED, // 1
REJECTED // 2
}
// 全局配置使用ordinal
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, true);
mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, false);
// 序列化结果:{"status": 1}
2. 在枚举字段上使用注解
JAVA
public class Order {
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
private Status status; // 序列化为数字
}
3. 使用@JsonValue和@JsonCreator自定义
JAVA
public enum Status {
PENDING("P"),
APPROVED("A"),
REJECTED("R");
private String code;
Status(String code) { this.code = code; }
@JsonValue // 序列化时使用code
public String getCode() { return code; }
@JsonCreator // 反序列化时根据code查找
public static Status fromCode(String code) {
return Arrays.stream(Status.values())
.filter(s -> s.code.equals(code))
.findFirst()
.orElse(null);
}
}
// 序列化结果:{"status": "A"}
// 可以从 {"status": "A"} 反序列化
推荐做法
- 默认使用名称:更易读,枚举顺序变化时不影响现有数据
- 避免使用ordinal:如果枚举顺序改变,会导致数据不一致
- 考虑向前兼容:使用自定义代码值比依赖名称或下标更稳定
总结:Jackson默认使用枚举名称,这是最安全、最可读的方式。