Сериализуйте один класс двумя разными способами с Джексоном
В одном из наших проектов мы используем веб-приложение на языке Java, говорящее с экземпляром MongoDB. В базе данных мы используем DBRefs
отслеживать некоторые объектные отношения. Мы (де) сериализуем с объектами POJO, используя Джексона (используя mongodb-jackson-mapper).
Тем не менее, мы используем те же POJO, чтобы затем (де) сериализовать во внешний мир, где наш интерфейс занимается представлением JSON.
Теперь нам нужен способ для сериализации для внешнего мира, чтобы содержать ссылочный объект из DBRef
(так что пользовательский интерфейс может представить полный объект), в то время как мы, очевидно, хотим иметь DBRef
записывается в базу данных, а не весь объект.
Прямо сейчас я написал некоторый непроверенный статический код вложенного класса:
public static class FooReference {
public DBRef<Foo> foo;
// FIXME how to ensure that this doesn't go into the database?
public Foo getFoo() {
return foo.fetch();
}
}
В идеале мне нужен способ аннотировать это так, чтобы я мог (де) сериализовать его либо с результатом getFoo(), либо без него, возможно, в зависимости от некоторого объекта конфигурации. Это возможно? Вы видите лучший способ сделать это?
2 ответа
При просмотре опций кажется, что вы можете аннотировать свойства, которые будут показаны только если View
передается в ObjectMapper
используется для сериализации. Таким образом, вы можете редактировать класс:
public static class FooReference {
public DBRef<Foo> foo;
@JsonView(Views.WebView.class)
public Foo getFoo() {
return foo.fetch();
}
}
и предоставить:
class Views {
static class WebView { }
}
и затем сериализовать после создания конфигурации с правильным представлением:
SerializationConfig conf = objectMapper.getSerializationConfig().withView(Views.WebView.class);
objectMapper.setSerializationConfig(conf);
Что бы затем сериализовать его. Если не указать представление при сериализации с помощью оболочки MongoDB, это будет означать, что метод будет игнорироваться. Свойства без аннотации JsonView по умолчанию сериализуются, поведение, которое вы можете изменить, указав:
objectMapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false);
Более подробная информация доступна на Jackson Wiki.
Оказывается, есть и другие альтернативы: есть Jackson MixIns, которые позволили бы вам переопределить (де) сериализованное поведение частей класса без изменения самого класса, а начиная с Jackson 2.0 (самый последний выпуск) есть фильтры, тоже.
Используйте кастом JSONSerializer
и применить вашу логику в serialize
метод:
public static class FooReference {
public DBRef<Foo> foo;
@JsonSerialize(using = CustomSerializer.class)
public Foo getFoo() {
return foo.fetch();
}
}
public class CustomSerializer extends JsonSerializer<Object> {
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
// jgen.writeObjectField ...
}
}