Spring Data Pagination在JSONView中没有返回任何结果

Pav*_*uri 8 java spring pagination json spring-mvc

我在我的REST控制器中使用Spring数据分页并返回Paged实体.我想在JSONViews的帮助下控制作为JSON返回的数据.

当我返回一个对象时,我能够实现结果.但是当我返回Page时,我收到空白的JSON作为回复.

以下是我的方法签名.

@JsonView(TravelRequestView.MyRequests.class)
@RequestMapping("/travel/requests")
public Page<TravelRequest> getUserTravelRequests(
            @RequestParam("ps") int pageSize, @RequestParam("p") int page,
            @RequestParam(defaultValue = "", value = "q") String searchString)
Run Code Online (Sandbox Code Playgroud)

我删除@JsonView注释时能够收到响应.

Nar*_*mha 10

如果您使用的是spring-boot,那么另一个更简单的解决方案是将以下内容添加到application.yml中

spring:
  jackson:
    mapper:
      DEFAULT_VIEW_INCLUSION: true
Run Code Online (Sandbox Code Playgroud)

或application.properties

spring.jackson.mapper.DEFAULT_VIEW_INCLUSION=true
Run Code Online (Sandbox Code Playgroud)

使用这种方法,我们的优势是保留了ObjectMapperSpring容器的托管,而不是创建一个新的ObjectMapper.因此,一旦我们使用spring管理的ObjectMapper,我们定义的任何Custom Serialzers仍将继续工作,例如CustomDateSerialzer

参考:http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html

  • 该解决方案忽略我的对象中的每个“@JsonView”注释并打印所有它们...... (4认同)

bla*_*eij 7

设置DEFAULT_VIEW_INCLUSION具有全局效果,而我们所需要的只是能够序列化Page对象.以下代码将为Page注册序列化程序,并且只是对代码的简单更改:

@Bean
public Module springDataPageModule() {
    return new SimpleModule().addSerializer(Page.class, new JsonSerializer<Page>() {
        @Override
        public void serialize(Page value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeStartObject();
            gen.writeNumberField("totalElements",value.getTotalElements());
            gen.writeNumberField("totalPages", value.getTotalPages());
            gen.writeNumberField("number", value.getNumber());
            gen.writeNumberField("size", value.getSize());
            gen.writeBooleanField("first", value.isFirst());
            gen.writeBooleanField("last", value.isLast());
            gen.writeFieldName("content");
            serializers.defaultSerializeValue(value.getContent(),gen);
            gen.writeEndObject();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

另一个(可以说是更优雅的)解决方案是注册以下ResponseBodyAdvice.它将确保您的REST端点仍将返回JSON数组,并设置HTTP标头"X-Has-Next-Page"以指示是否有更多数据.优点是:1)没有额外的计数(*)查询到您的数据库(单个查询)2)响应更优雅,因为它返回一个JSON数组

/**
 * ResponseBodyAdvice to support Spring data Slice object in JSON responses.
 * If the value is a slice, we'll write the List as an array, and add a header to the HTTP response
 *
 * @author blagerweij
 */
@ControllerAdvice
public class SliceResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Slice) {
            Slice slice = (Slice) body;
            response.getHeaders().add("X-Has-Next-Page", String.valueOf(slice.hasNext()));
            return slice.getContent();
        }
        return body;
    }
}
Run Code Online (Sandbox Code Playgroud)


Pav*_*uri 5

我实际上找到了一种更简单、更好的方法来做到这一点。我遇到的问题是我无法在收到的 Page 对象上设置 @JsonView 注释。因此,我创建了 Page 接口的实现并向其中添加了 JsonView。我现在返回的是 MyPage,而不是返回 Page

public class MyPage<T> implements Page<T> {

    private Page<T> pageObj;

    public MyPage(Page<T> pageObj) {
        this.pageObj = pageObj;
    }

    @JsonView(PaginatedResult.class)
    @Override
    public int getNumber() {
        return pageObj.getNumber();
    }

    @Override
    public int getSize() {
        return pageObj.getSize();
    }

    @JsonView(PaginatedResult.class)
    @Override
    public int getNumberOfElements() {
        return pageObj.getNumberOfElements();
    }

    @JsonView(PaginatedResult.class)
    @Override
    public List<T> getContent() {
        return pageObj.getContent();
    }

    @Override
    public boolean hasContent() {
        return pageObj.hasContent();
    }

    @Override
    public Sort getSort() {
        return pageObj.getSort();
    }

    @JsonView(PaginatedResult.class)
    @Override
    public boolean isFirst() {
        return pageObj.isFirst();
    }

    @JsonView(PaginatedResult.class)
    @Override
    public boolean isLast() {
        return pageObj.isLast();
    }

    @Override
    public boolean hasNext() {
        return pageObj.hasNext();
    }

    @Override
    public boolean hasPrevious() {
        return pageObj.hasPrevious();
    }

    @Override
    public Pageable nextPageable() {
        return pageObj.nextPageable();
    }

    @Override
    public Pageable previousPageable() {
        return pageObj.previousPageable();
    }

    @Override
    public Iterator<T> iterator() {
        return pageObj.iterator();
    }

    @JsonView(PaginatedResult.class)
    @Override
    public int getTotalPages() {
        return pageObj.getTotalPages();
    }

    @JsonView(PaginatedResult.class)
    @Override
    public long getTotalElements() {
        return pageObj.getTotalElements();
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 什么是分页结果?将被映射的类? (2认同)

Kir*_*shi 4

尝试使用下面的代码,

@Configuration
public class MyInterceptorConfig extends WebMvcConfigurerAdapter{

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
      MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
      ObjectMapper mapper = new ObjectMapper() {
        private static final long serialVersionUID = 1L;
        @Override
        protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) {
          // replace the configuration with my modified configuration.
          // calling "withView" should keep previous config and just add my changes.
          return super._serializerProvider(config.withView(TravelRequestView.MyRequests.class));
        }        
      };
      mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
      converter.setObjectMapper(mapper);
      converters.add(converter);
    }
Run Code Online (Sandbox Code Playgroud)

虽然我不想因此而获得功劳,但这是来自的参考

Jackson JsonView 未应用

它将检索实体的所有用 jsonview (TravelRequestView.MyRequests.class) 注释的变量以及所有未用 jsonview 注释的变量。如果您不想要对象的某些属性,请使用不同的视图进行注释。