У меня есть класс, который при сериализации должен сериализовать один из его членов на своем месте. Мой класс:Пользовательский сериализатор с MongoDB, Jackson и 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 был бы чрезвычайно сложным, потому что он является абстрактным корневым классом. Это может быть достигнуто через Джексон, однако, с несколькими примечаниями:
@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 {
...
}
Я испытал это с помощью Джексона сериализации и десериализации экземпляры MyClass, и она работает точно так же, как предполагалось.
Мой код приложения немного сложнее. У меня есть ContainerClass
, который имеет тип MyClass
. Я пытаюсь сериализация экземпляра ContainerClass
через MongoJack:
// 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
, который не является тем, что я хочу. Это делает меня почти уверенным, что проблема заключается в моем пользовательском сериализаторе, но я не уверен, как еще я должен его написать.
Заранее спасибо.
Отлично! Это ответило на мой первоначальный вопрос; Я не могу поверить, что никогда не знал о '@ JsonValue'. Я попробовал '@ JsonCreator', но у меня проблемы.Он жалуется, что абстрактные типы либо должны быть сопоставлены конкретным типам (которые ** ** выполняются в аннотациях абстрактного класса), имеют собственный десериализатор (что, вероятно, то, что я буду делать), либо создаются с помощью дополнительных (что я не понимаю). В любом случае, если у вас есть предложение о том, как исправить это, это будет здорово, но если нет, пользовательский десериализатор уже работает. Еще раз спасибо! – user1236874
Возможно, стоит задать другой вопрос здесь или в списках рассылки: я не знаю, что делать, но это должно быть возможным, независимо от проблемы. Но с пользовательским десериализатором, возможно, не стоит беспокоиться об этом. – StaxMan