Jos*_*nez 3 java serialization pojo mongodb
我有一个现有对象,想使用 Java + POJO 编解码器在 MongoDB 中序列化。由于某种原因,驱动程序尝试创建枚举实例而不是使用 valueOF:
org.bson.codecs.configuration.CodecConfigurationException: Failed to decode 'phase'. Failed to decode 'value'. Cannot find a public constructor for 'SimplePhaseEnumType'.
at org.bson.codecs.pojo.PojoCodecImpl.decodePropertyModel(PojoCodecImpl.java:192)
at org.bson.codecs.pojo.PojoCodecImpl.decodeProperties(PojoCodecImpl.java:168)
at org.bson.codecs.pojo.PojoCodecImpl.decode(PojoCodecImpl.java:122)
at org.bson.codecs.pojo.PojoCodecImpl.decode(PojoCodecImpl.java:126)
at com.mongodb.operation.CommandResultArrayCodec.decode(CommandResultArrayCodec.java:52)
Run Code Online (Sandbox Code Playgroud)
枚举:
public enum SimplePhaseEnumType {
PROPOSED("Proposed"),
INTERIM("Interim"),
MODIFIED("Modified"),
ASSIGNED("Assigned");
private final String value;
SimplePhaseEnumType(String v) {
value = v;
}
public String value() {
return value;
}
public static SimplePhaseEnumType fromValue(String v) {
for (SimplePhaseEnumType c: SimplePhaseEnumType.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}}
Run Code Online (Sandbox Code Playgroud)
并且该类使用枚举(仅显示相关字段):
public class SpecificPhaseType {
protected SimplePhaseEnumType value;
protected String date;
public SimplePhaseEnumType getValue() {
return value;
}
public void setValue(SimplePhaseEnumType value) {
this.value = value;
}}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方法来注释类,以告诉驱动程序在遇到这些字段时使用不同的方法来序列化/反序列化这些字段。我知道如何在序列化/反序列化期间跳过它们,但这并不能解决问题:
public class SpecificPhaseType {
@BsonIgnore
protected SimplePhaseEnumType value;
Run Code Online (Sandbox Code Playgroud)
关于我可以在哪里查看(代码、文档)有什么帮助吗?我已经检查了PojoQuickTour.java,MongoDB 驱动程序快速入门 - POJO和POJO - 普通旧 Java 对象
谢谢!
——何塞
我想出了该怎么做,您首先需要编写一个自定义编解码器来将枚举读取和写入为字符串(如果您想节省空间,序数是另一种选择,但字符串对我来说已经足够了):
package com.kodegeek.cvebrowser.persistence.serializers;
import com.kodegeek.cvebrowser.entity.SimplePhaseEnumType;
import org.bson.BsonReader;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
public class SimplePhaseEnumTypeCodec implements Codec<SimplePhaseEnumType>{
@Override
public SimplePhaseEnumType decode(BsonReader reader, DecoderContext decoderContext) {
return SimplePhaseEnumType.fromValue(reader.readString());
}
@Override
public void encode(BsonWriter writer, SimplePhaseEnumType value, EncoderContext encoderContext) {
writer.writeString(value.value());
}
@Override
public Class<SimplePhaseEnumType> getEncoderClass() {
return SimplePhaseEnumType.class;
}
}
Run Code Online (Sandbox Code Playgroud)
然后您需要注册新的编解码器,以便 MongoDB 可以使用您的类处理枚举:
/**
* MongoDB could not make this any simpler ;-)
* @return a Codec registry
*/
public static CodecRegistry getCodecRegistry() {
final CodecRegistry defaultCodecRegistry = MongoClient.getDefaultCodecRegistry();
final CodecProvider pojoCodecProvider = PojoCodecProvider.builder().register(packages).build();
final CodecRegistry cvePojoCodecRegistry = CodecRegistries.fromProviders(pojoCodecProvider);
final CodecRegistry customEnumCodecs = CodecRegistries.fromCodecs(
new SimplePhaseEnumTypeCodec(),
new StatusEnumTypeCodec(),
new TypeEnumTypeCodec()
);
return CodecRegistries.fromRegistries(defaultCodecRegistry, customEnumCodecs, cvePojoCodecRegistry);
}
Run Code Online (Sandbox Code Playgroud)
Jackson 可以更轻松地使用 @JsonSerializer / @JsonDeserializer 等注释来注册自定义序列化器/反序列化器,而 Mongo 则强制您处理注册表。没什么大不了的 :-)
您可以在此处查看完整的源代码。希望这可以为必须处理类似问题的任何人节省一些时间。