繁体   English   中英

无法使用Java MongoDB驱动程序使用枚举读取或序列化POJO

[英]Cannot read or serialize POJO with enumerations using Java MongoDB driver

我有一个现有对象,我想使用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)

枚举:

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);
}}

并且该类使用枚举(仅显示相关字段):

public class SpecificPhaseType {

protected SimplePhaseEnumType value;
protected String date;

public SimplePhaseEnumType getValue() {
    return value;
}

public void setValue(SimplePhaseEnumType value) {
    this.value = value;
}}

我正在寻找一种注释类的方法,以告知驱动程序在遇到这些字段时使用其他方法来序列化/反序列化这些字段。 我知道如何在序列化/反序列化期间跳过它们,但这不能解决问题:

public class SpecificPhaseType {

@BsonIgnore
protected SimplePhaseEnumType value;

对我的外观有任何帮助(代码,文档)? 我已经检查过PojoQuickTour.javaMongoDB驱动程序快速入门 -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;
    }
}

然后,您需要注册新的编解码器,以便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);
}

Jackson使使用@JsonSerializer / @JsonDeserializer等注解注册自定义序列化器/反序列化器更加容易,而Mongo则迫使您处理注册表。 没有大碍 :-)

您可以在此处查看完整的源代码。 希望这可以为需要处理类似问题的任何人节省一些时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM