Spring Data Couchbase无需修改现有代码如何存储Enum名称而非值
Spring Data Couchbase 枚举存储无侵入调整方案
核心原理:Spring Data Couchbase 默认使用 Jackson 做 JSON 序列化,你遇到的问题是因为 Foo 枚举重写了 toString() 返回自定义 value,序列化时默认调用了该方法。通过调整 Jackson 序列化规则即可实现存储枚举 name() 值,完全不需要修改现有业务代码,同时支持 Map 键场景的枚举处理。
方案一:全局注册自定义枚举序列化模块(最简便,无需修改现有配置)
直接新增一个 Jackson 模块 Bean,Spring Boot 会自动将该模块注入到包括 Couchbase 在内的所有使用的 ObjectMapper 中:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; @Configuration public class FooEnumSerializationConfig { @Bean public SimpleModule customFooEnumModule() { SimpleModule module = new SimpleModule("FooEnumSerialization"); // 枚举值序列化 module.addSerializer(Foo.class, new StdSerializer<Foo>(Foo.class) { @Override public void serialize(Foo value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(value.name()); } }); // 枚举作为Map键的序列化 module.addKeySerializer(Foo.class, new StdSerializer<Foo>(Foo.class) { @Override public void serialize(Foo value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeFieldName(value.name()); } }); // 枚举值反序列化 module.addDeserializer(Foo.class, new StdDeserializer<Foo>(Foo.class) { @Override public Foo deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { return Foo.valueOf(p.getText()); } }); // 枚举作为Map键的反序列化 module.addKeyDeserializer(Foo.class, new com.fasterxml.jackson.databind.KeyDeserializer() { @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { return Foo.valueOf(key); } }); return module; } }
方案二:Couchbase 转换器单独配置
如果项目中 Couchbase 使用独立的 ObjectMapper,不继承全局配置,可以在 Couchbase 配置类中单独调整:
import org.springframework.context.annotation.Configuration; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter; @Configuration public class CouchbaseConfig extends AbstractCouchbaseConfiguration { // 原有Couchbase配置(连接信息、桶配置等)保持不变 @Override public MappingCouchbaseConverter mappingCouchbaseConverter() throws Exception { MappingCouchbaseConverter converter = super.mappingCouchbaseConverter(); // 注册上面定义的customFooEnumModule模块 converter.getObjectMapper().registerModule(new FooEnumSerializationConfig().customFooEnumModule()); // 也可以全局开启枚举用name序列化,不需要单独定义序列化器: // converter.getObjectMapper().configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, false); // converter.getObjectMapper().configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, false); return converter; } }
验证
配置完成后,Couchbase 中存储的 Universe 下的 bar 字段的键会直接存储 Moon、Star、Sun 枚举名称,不会再存 Night、Day 等自定义value,读取时也能自动反序列化为 Foo 枚举,完全兼容现有业务逻辑。
内容的提问来源于stack exchange,提问作者Priya
相关产品推荐
相关产品推荐

