2017-01-18 5 views
2

Я создаю приложение REST Java с JAX-RS.Список десериализации Java REST

В контексте приложения, у меня есть следующие классы боба:

public class ContentView { 
    // Field definitions, getters/setters 
} 

public class ArticleDetailView extends ContentView { 
    // more definitions, getters/setters 
} 

public class UpsellDetailView extends ContentView { 
    // more definitions, getters/setters 
} 

UpsellDetailView и ArticleDetailView имеют больше атрибутов и оба они расширяют ContentView. У меня есть все правильно подключенные mappers, поэтому все экземпляры каждого соответствующего класса получают все свои свойства правильно. Я не использую никаких дополнительных карт - свойства объектов получают десериализацию на основе публичных геттеров в соответствующих классах компонентов.

SeriesDetailView похож:

public class SeriesDetailView extends SeriesLiteView { 
    private List<Content> content; 

    @JsonIgnore //We don't want content appear on the Series detail page 
    public List<Content> getContent() { 
     return content; 
    } 

    public void setContent(List<Content> content) { 
     this.content = content; 
    } 
} 

Теперь у меня есть класс ресурсов REST следующим образом:

@Produces({MediaType.APPLICATION_JSON}) 
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED}) 
@Path("/") 
public class ApiSiteResource extends AbstractContentResource { 
... 
    @GET 
    @Path("/series/{uuid}/contents") 
    public List<ContentView> getSessionsForSeries(@Context HttpServletRequest request, @Context HttpServletResponse response, @BeanParam ApiParams params) { 
     final SeriesDetailView series = seriesService.findByUuid(params.getUuid()); 
     if (series == null) { 
      response.setStatus(SC_NOT_FOUND); 
      return null; 
     } 
     List<ContentView> contentViewList = contentMapper.map(series.getContent()); 
     List<ContentView> results = contentViewList.stream().map(e -> mapContent(e, e.getUuid())).collect(Collectors.toList()); 
     return results; 
    } 

    @GET 
    @Path("/contents/{uuid}") 
    public ContentView uniqueContent(@Context HttpServletRequest request, @Context HttpServletResponse response, @BeanParam ApiParams params) { 
     ContentView beanView = contentService.findByUuid(params.getUuid()); 
     if (beanView == null) { 
      response.setStatus(SC_NOT_FOUND); 
      return null; 
     } 
     beanView = mapContent(beanView, params.getUuid()); 
     return beanView; 
    } 

    private ContentView mapContent(ContentView beanView, String uuid){ 
     if (ArticleType.TypeGroup.upsell.toString().equals(beanView.getType())) { 
      UpSell upsell = ((UpSell)contentService.findByUuidRaw(uuid)); 
      beanView = (UpsellDetailView)upsellMapper.map(upsell); 
      rewriteBodyHtml(beanView, upsell.getBody()); 
     } 
     else if (ArticleType.TypeGroup.article.toString().equals(beanView.getType()) || 
       ArticleType.TypeGroup.audio.toString().equals(beanView.getType()) || 
       ArticleType.TypeGroup.video.toString().equals(beanView.getType())) { 
      Article article = ((Article)contentService.findByUuidRaw(uuid)); 
      beanView = (ArticleDetailView)articleMapper.map(article); 
      rewriteBodyHtml(beanView, article.getBody()); 
     } 
     return beanView; 
    } 
} 

Теперь вот проблема:

, когда я взываю/содержание/{ uuid} в браузере, я получаю полностью десериализованный правильный тип контента json (Article или UpsellDetailView), но

Когда я вызываю/series/{uuid}/contents, я получаю список элементов json короткой формы, соответствующих структуре ContentView.

Я подтверждаю, что результаты List в getSessionsForSeries() представляют собой список правильных типов (Article или UpsellDetailView).

Но я не могу найти для своей жизни, почему они не получают должным образом десериализованного, когда в Списке. Что мне не хватает?

+0

Вы можете включить код класса «SeriesDetailView», пожалуйста? Я вижу, что вы обновляете результаты в функции «getSessionsForSeries» -> –

+0

@SaifMasadeh, которая была добавлена, спасибо –

+0

Я вижу, что вы поднимаете результаты в функции «getSessionsForSeries» -> Список результатов и я думаю, именно поэтому вы получаете короткую версию результата, а в «uniqueContent» вы сверкаете результаты. –

ответ

1

Вот ответ:

По какой-то причине, сериализатор Листа был перепутался и был когда сериализация был недобросовестным заявленным содержанием класса (ContentView).

Если у кого-то есть идея, почему я буду благодарен за просвещение.

Таким образом, я должен был использовать грубую силу и обеспечить свою собственную сериализацию (не отметить тип ответа методы изменяется на строки):

@GET 
@Path("/series/{uuid}/contents") 
public String getSessionsForSeries(@Context HttpServletRequest request, @Context HttpServletResponse response, @BeanParam ApiParams params) { 
    final SeriesDetailView series = seriesService.findByUuid(params.getUuid()); 
    if (series == null) { 
     response.setStatus(SC_NOT_FOUND); 
     return null; 
    } 
    List<ContentView> contentViewList = contentMapper.map(series.getContent()); 
    List<ContentView> results = contentViewList.stream() 
      .map(e -> mapContent(e, e.getUuid())).collect(Collectors.toList()); 
    ObjectMapper objectMapper = new ObjectMapper(); 

    try { 
     return objectMapper.writeValueAsString(results); 
    } catch (IOException e) { 
     response.setStatus(SC_INTERNAL_SERVER_ERROR); 
     return null; 
    } 
} 

Благодаря учебник здесь: http://www.davismol.net/2015/03/05/jackson-json-deserialize-a-list-of-objects-of-subclasses-of-an-abstract-class/

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