簡體   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