Java 使用MongoDB、Jackson和MongoJack的自定义序列化程序

Java 使用MongoDB、Jackson和MongoJack的自定义序列化程序,java,json,mongodb,serialization,jackson,Java,Json,Mongodb,Serialization,Jackson,我有一个类,当序列化时,应该在它的位置序列化它的一个成员。我的班级是: @JsonSerialize(using = MyClassSerializer.class) public class MyClass implements Serializable { /** * A default ID for this class for serialization. */ private static final long serialVersionUID =

我有一个类,当序列化时,应该在它的位置序列化它的一个成员。我的班级是:

@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());
    }
}
我已经使用Jackson对MyClass的实例进行了序列化和反序列化测试,结果完全符合预期

我的应用程序代码有点复杂。我有一个
container类
,其成员类型为
MyClass
。我试图通过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);
如果我从
MyClass
中删除
@JsonSerialize
,我可以让它工作,但是这会导致整个
MyClass
实例被序列化,这不是我想要的。这让我几乎可以肯定问题出在我的自定义序列化程序上,但我不确定我应该如何编写它


提前谢谢。

一个可能有用的提示:当使用多态类型时,调用的方法是:

serializeWithType(...)
而不是
序列化(…)
。因此,您需要实现该方法;通常情况下,它将是简单的:

typeSer.writeTypePrefixForObject(value, jgen);
// implement actual content serialization, or delegate here:
this.serialize(...);
typeSer.writeTypeSuffixForObject(value, jgen);
但您可能想看看标准的Jackson序列化程序。唯一真正的区别是,
serialize
需要直接输出START\u对象和END\u对象,这里我们必须要求
TypeSerializer
添加它们。这是必要的,因为
类型id
包含实际上可能会改变这些(我可以详细说明,但现在这应该足够了)

然而,这里可能有更简单的解决方案。如果您可以在想要使用的成员上添加
@JsonValue
注释,而不是整个对象(直接或通过mix-in),那么应该可以做到:

@JsonValue
public OtherClass getOtherClass()...
如果需要反序列化,可以使用
@JsonCreator
如下:

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

伟大的这回答了我最初的问题;我真不敢相信我从来都不知道
@JsonValue
。我试过
@JsonCreator
,但有点麻烦。它抱怨说,抽象类型要么需要映射到具体类型(这是在抽象类的注释中完成的),要么需要自定义反序列化器(这可能就是我将要做的),要么需要用其他类型信息实例化(我不理解)。无论如何,如果您对如何解决这个问题有建议,那就太好了,但是,如果没有,自定义反序列化程序已经在工作了。再次感谢!在这里或邮件列表上可能值得再问一个问题:我现在不知道,但不管是什么问题,都应该可以解决。但对于自定义反序列化程序,此时可能不值得担心。
@JsonValue
public OtherClass getOtherClass()...
@JsonCreator
public MyClass(OtherClass surrogate) { ... }