我有一个类,在序列化时,应该将其中一个成员序列化。我的班级是:
@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编写自定义序列化程序也会非常复杂,因为它是一个抽象的根类。这可以通过杰克逊来实现,但需要注意一些注释:
@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的实例进行序列化和反序列化,并且它的工作方式完全符合预期。
我的应用程序代码有点复杂。我有ContainerClass
,其成员类型为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);
但是,我收到以下错误:
...
Caused by: java.lang.IllegalArgumentException: can't serialize class my.package.MyClass
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270)
...
如果我从@JsonSerialize
中移除MyClass
,我可以使用它,但是这会导致整个MyClass
实例被序列化,这不是我想要的。这让我几乎可以肯定问题在于我的自定义序列化程序,但我不确定我应该怎么写它。
提前谢谢。
答案 0 :(得分:1)
一个可能有用的快速说明:当使用多态类型时,调用的方法将是:
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) { ... }