2015-10-29 3 views
1

Я сериализую некоторые существующие объекты с помощью Jackson 2.22, используя функцию MixIn, чтобы отделить реальный объект от конфигурации аннотаций Jackson.Как добавить производные свойства в сериализованный класс Jackson 2?

На самом деле мой mixin - это интерфейс, который объявляет те же методы целевого класса и аннотирует их, вот пример.

Целевой класс:

public class Product { 

    // ... 

    public String getName(); 

    public String getDescription(); 

    public String getPrice(); 

    public String getFinalPrice(); 

    public String getDiscount(); 

    // ... 

} 

и Mixin:

public interface ProductApi { 

    @JsonProperty 
    public String getName(); 

    @JsonProperty("price") 
    public String getFinalPrice(); 

} 

Мой JSON должен иметь больше некоторую информацию, вычисленная из нескольких методов или полей целевого класса.

Возможно ли это в Джексоне?

Я попытался превратить mixin в класс и добавив новый метод там, но это не сработало.

public class ProductApi { 

    @JsonProperty 
    public String getName(); 

    @JsonProperty("price") 
    public String getFinalPrice(); 

    @JsonProperty("images") 
    public List<String> getImages() { /* ... */ } 

} 

Я думаю, это потому, что Mixin только обеспечивает аннотации для целевого класса, но тот, который читается для сериализации.

Конечно, если я изменю объект для сериализации с новым подклассом, который содержит новый метод, который мне нужен, это работает, но объекты поступают из наших слоев служб, и это будет означать, что я должен переписать все эти методы ,

Я использую Джексона с Джерси, поэтому не хочу менять Джексона с другой библиотекой.

+0

поэтому, если я понимаю, вы передаете экземпляр 'Product' в ObjectMapper и потому, что' Product' реализует 'ProductApi', то ObjectMapper читает аннотации оттуда –

+0

@sharonbn. Вся история заключается в том, что' Product' возвращается внутри пользовательский объект, инкапсулированный в JAX-RS [объект ответа] (http://jax-rs-spec.java.net/nonav/2.0/apidocs/javax/ws/rs/core/Response.html), сериализация которого опосредована пользовательским «ObjectMapper», предоставляемым [ContextResolver] (https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html?javax/ws/rs/core/Configurable.html), который настраивает его с помощью mixin, но да, вот что в итоге происходит :-) – watery

ответ

0

Вот как я это сделал.

Решение состоит в том, чтобы указать пользовательскую реализацию JsonSerializer в полевой приемник.

Прежде всего, я изменил mixin interface на class, который расширяет класс сущности (цели), чтобы он мог получить доступ к данным целевого класса.

public class ProductApi extends Product { 

    @JsonProperty 
    @Override 
    public String getName() { 
     return super.getName(); 
    }; 

    // ... 

} 

Далее, я реализован JsonSerializer, что бы создать производное свойство Я хочу:

public static class ImagesSerializer extends JsonSerializer<String> { 

    @Override 
    public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
     Product p = (Product) jgen.getCurrentValue(); 

     int num = p.getNumberOfImages(); 

     List<String> imgs = new ArrayList<String>(num); 

     for(int i = 0; i < num; i++) { 
      String src = "/include/images/showImage.jsp?"+"id="+p.getId()+"&number="+i; 
      imgs.add(src); 
     } 

     provider.defaultSerializeValue(imgs, jgen); 
    } 

} 

Это действительно простую реализацию, дополнительные проверки безопасности должны быть сделаны.

Что это такое, в основном, извлекает весь экземпляр объекта из генератора JSON, создает пользовательский объект, а затем попросит Джексона сериализовать его.
Я реализовал его внутри своего ProductApi как статический класс, но просто для простоты.

Наконец, сериализатор должен быть связан с JsonProperty аннотированного поля:

public class ProductApi extends Product { 

    @JsonProperty 
    @Override 
    public String getName() { 
     return super.getName(); 
    }; 

    // ... 

    @JsonSerialize(using=ImagesSerializer.class) 
    @JsonProperty("images") 
    @Override 
    public String getImage() { // in my entity this returns an image number, whereas in my JSON I want a list of URLs 
     return ""; 
    } 

    // ... 

} 

В качестве примечания, кажется, что возвращаемое значение методы getImage() не используется.

-1

Почему бы вам просто не сделать несколько полей, которые должны быть сериализованы и использовать Gson для этого?

+0

Я забыл добавить, что я использую Джексона с Джерси, поэтому я хочу придерживаться этой библиотеки. Перейдем к редактированию моего вопроса. – watery

+0

«Создание некоторых полей» и сериализация их также достижимы в Джексоне. на самом деле, Джексон превосходит gson feature-wise –

Смежные вопросы