簡體   English   中英

使用MongoDB,Jackson和MongoJack的自定義序列化器

[英]Custom Serializer with MongoDB, Jackson, and MongoJack

我有一個類,當進行序列化時,應該在其位置序列化其成員之一。 我的課是:

@JsonSerialize(using = MyClassSerializer.class)
public class MyClass implements Serializable {

    /**
     * A default ID for this class for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * A member of this object.
     */
    private final OtherClass otherClass;

    ...

    /**
     * Returns the instance of the member object.
     * 
     * @return The instance of the member object.
     */
    public OtherClass getOtherClass() {
        return otherClass;
    }
}

為此,我創建了一個非常簡單的自定義序列化程序:

public class MyClassSerializer extends JsonSerializer<MyClass> {
    /**
     * Serializes only the OtherClass field.
     */
    @Override
    public void serialize(
        final MyClass myClass,
        final JsonGenerator generator,
        final SerializerProvider provider)
        throws IOException, JsonProcessingException {

        // Write the schema.
        generator.writeObject(myClass.getOtherClass());
    }
}

這是做這樣的事情的最簡單(也是最正確的方法)。 即使我願意,為OtherClass編寫自定義序列化程序也將非常復雜,因為它是抽象的根類。 可以通過Jackson來完成,但是要有一些注釋:

@JsonTypeInfo(
    use = Id.NAME,
    include = As.PROPERTY,
    property = OtherClass.JSON_KEY_TYPE,
    defaultImpl = OtherClassDefault.class)
@JsonSubTypes({
    @JsonSubTypes.Type(
        value = SubOtherClass1.class,
        name = SubOtherClass1.TYPE_ID),
    @JsonSubTypes.Type(
        value = SubOtherClass2.class,
        name = SubOtherClass2.TYPE_ID),
    @JsonSubTypes.Type(
        value = SubOtherClass3.class,
        name = SubOtherClass3.TYPE_ID),
    @JsonSubTypes.Type(
        value = SubOtherClass4.class,
        name = SubOtherClass4.TYPE_ID),
    @JsonSubTypes.Type(
        value = SubOtherClass5.class,
        name = SubOtherClass5.TYPE_ID) })
@JsonAutoDetect(
    fieldVisibility = Visibility.DEFAULT,
    getterVisibility = Visibility.NONE,
    setterVisibility = Visibility.NONE,
    creatorVisibility = Visibility.DEFAULT)
public abstract class OtherClass implements Serializable {
    ...
}

我已經使用Jackson進行了序列化和反序列化MyClass實例的測試,它完全可以按預期工作。

我的應用程序代碼稍微復雜一些。 我有一個具有MyClass類型成員的ContainerClass 我嘗試通過MongoJack序列化ContainerClass的實例:

// Get the authentication token collection.
JacksonDBCollection<ContainerClass, Object> collection =
    JacksonDBCollection
        .wrap(
            MongoBinController
                .getInstance()
                .getDb()
                .getCollection(COLLECTION_NAME),
            ContainerClass.class);

// Save it.
collection.insert(container);

但是,我收到以下錯誤:

...
Caused by: java.lang.IllegalArgumentException: can't serialize class my.package.MyClass
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270)
    ...

如果從MyClass刪除@JsonSerialize ,我可以使它工作,但是這導致整個MyClass實例被序列化,這不是我想要的。 這幾乎使我確定問題出在我的自定義序列化程序中,但是我不確定應該如何編寫它。

先感謝您。

快速說明可能會有所幫助:使用多態類型時,調用的方法將是:

serializeWithType(...)

而不是serialize(...) 因此,您將需要實現該方法。 通常它會很簡單:

typeSer.writeTypePrefixForObject(value, jgen);
// implement actual content serialization, or delegate here:
this.serialize(...);
typeSer.writeTypeSuffixForObject(value, jgen);

但您可能想看看標准的Jackson序列化器。 唯一真正的區別是,雖然serialize需要直接輸出START_OBJECT,END_OBJECT,但在這里我們必須要求TypeSerializer添加它們。 這是必需的,因為type id包含實際上可能會更改這些內容(我可以對此進行詳細說明,但現在就足夠了)。

但是:這里可能有更簡單的解決方案。 如果可以在要使用的成員上添加@JsonValue批注而不是整個對象(直接或通過混合),則可以實現此目的:

@JsonValue
public OtherClass getOtherClass()...

如果需要反序列化,則可以使用@JsonCreator例如:

@JsonCreator
public MyClass(OtherClass surrogate) { ... }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM