Java枚举序列化为含name/value属性JSON对象的实现方案
枚举自动序列化为name+value结构落地实现
你之前尝试的@JsonValue方案完全可行,只需要修正几个语法和访问权限问题即可,不需要编写全量DTO转换逻辑,以下是两种可直接运行的实现方式:
方案1:@JsonValue 注解实现(最轻量,零额外配置)
只需要修正两个类的代码即可:
- 补全包装类
MyTypeWrapper的构造方法与getter方法(Jackson默认通过public getter读取序列化字段)
public class MyTypeWrapper { private String name; private String value; // 新增全参构造 public MyTypeWrapper(String name, String value) { this.name = name; this.value = value; } // 补全字段getter public String getName() { return name; } public String getValue() { return value; } }
- 修正枚举类中
@JsonValue修饰的方法:方法必须为public类型,补全语法逻辑
public enum MyType { TT("Time Tu"), TD("Time dust"); MyType(String value) { this.value = value; } private final String value; public String getValue() { return value; } // 修正:方法改为public,补全方法体,直接调用枚举内置的name()方法获取枚举实例名 @JsonValue public MyTypeWrapper getWrapper() { return new MyTypeWrapper(this.name(), this.value); } @Override public String toString() { return value; } }
说明:该方案修改完成后立即生效,所有返回
MyType类型的字段都会自动序列化为{"name":"实例名","value":"自定义值"}结构,不需要任何额外全局配置。
方案2:自定义Jackson序列化器(适合多枚举统一规则场景)
如果不想在枚举内部耦合包装类逻辑,或者需要给多个枚举统一序列化规则,可以用自定义序列化器实现:
- 编写对应枚举的序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; public class MyTypeSerializer extends StdSerializer<MyType> { public MyTypeSerializer() { super(MyType.class); } @Override public void serialize(MyType myType, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); gen.writeStringField("name", myType.name()); gen.writeStringField("value", myType.getValue()); gen.writeEndObject(); } }
- 绑定序列化器,两种方式二选一即可:
- 方式A:直接在枚举类上加注解绑定,仅对当前枚举生效
import com.fasterxml.jackson.databind.annotation.JsonSerialize; @JsonSerialize(using = MyTypeSerializer.class) public enum MyType { // 原有枚举代码不需要做任何修改 TT("Time Tu"), TD("Time dust"); MyType(String value) { this.value = value; } private final String value; public String getValue() { return value; } }
- 方式B:全局注册到Jackson配置,不需要改枚举类,Spring Boot项目直接添加配置类即可
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer enumCustomizer() { return builder -> builder.serializerByType(MyType.class, new MyTypeSerializer()); } }
补充反序列化支持(可选)
如果需要将前端传入的{"name":"TT","value":"xxx"}结构反序列化为枚举实例,额外编写对应反序列化器即可:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 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); // 直接根据name字段匹配枚举实例即可 return MyType.valueOf(node.get("name").asText()); } }
绑定方式和序列化器一致,在枚举上加@JsonDeserialize(using = MyTypeDeserializer.class),或者全局注册到ObjectMapper即可。
效果验证
修改完成后直接返回JPA实体MyObject,不需要任何DTO转换,返回的JSON结构自动符合预期:
{ "id": 1, "number": "NO001", "myType": { "name": "TT", "value": "Time Tu" } }
避坑提示:JPA层面的枚举持久化配置
@Enumerated(EnumType.STRING)和JSON序列化逻辑互不干扰,正常添加即可,不会影响序列化结果。
内容的提问来源于stack exchange,提问作者Джейк Морган
相关产品推荐
相关产品推荐

