Jackson枚举配置@JsonFormat为OBJECT时如何兼容字符串和对象反序列化
枚举保持@JsonFormat shape为OBJECT时兼容字符串+对象格式反序列化方案
问题根因
类上标注的@JsonFormat(shape = JsonFormat.Shape.OBJECT)会让Jackson默认将反序列化输入识别为JSON对象,当输入为字符串类型时,默认解析逻辑不会匹配到单独添加的Delegating模式@JsonCreator方法,因此你之前的尝试不生效。
可行方案
方案1:统一使用JsonNode参数的@JsonCreator方法(最简便)
删除原来的两个反序列方法,新增一个通用Creator方法,自行判断输入类型即可,无需修改现有@JsonFormat注解,也无需额外配置:
@JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum MyType { // 补充缺失的value字段定义 private final String value; @JsonProperty("MYENUM") MYENUM("MyEnum"); public final String name = name(); MyType(String value) { this.value = value; } // 通用反序列化方法 @JsonCreator public static MyType deserialize(JsonNode node) { String name; // 兼容字符串输入和对象输入 if (node.isTextual()) { name = node.asText(); } else { name = node.get("name").asText(); } return MyType.valueOf(name); } }
方案2:自定义反序列化器
如果需要更复杂的反序列化逻辑,可以单独实现反序列化器,绑定到枚举类即可:
- 实现自定义反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; public class MyTypeDeserializer extends StdDeserializer<MyType> { public MyTypeDeserializer() { super(MyType.class); } @Override public MyType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); String name = node.isTextual() ? node.asText() : node.get("name").asText(); return MyType.valueOf(name); } }
- 给枚举类添加反序列化器绑定注解
@JsonFormat(shape = JsonFormat.Shape.OBJECT) @JsonDeserialize(using = MyTypeDeserializer.class) public enum MyType { // 原有枚举逻辑不变 }
两种方案都可以同时支持"type": {"name":"MYENUM"}和"type": "MYENUM"两种反序列化格式,且不会影响原有序列化输出为对象的逻辑。
内容的提问来源于stack exchange,提问作者orion_kid
相关产品推荐
相关产品推荐

