【问题标题】:spring MVC use @JsonView on spring-data Pagespring MVC 在 spring-data 页面上使用 @JsonView
【发布时间】:2015-07-25 02:44:38
【问题描述】:

我在 Jhipster 项目中使用 Spring-MVC、Spring-data-jpa、jackson。

我设法在一个对象上使用了@JsonView 注释,并且当其余控制器中的方法返回类型ResponseEntity<List<MyObject>> 时它运行良好,但当方法返回类型为ResponseEntity<Page<MyObject>> 时我无法使其运行。

我尝试将MapperFeature.DEFAULT_VIEW_INCLUSION 设置为true(默认为false)。当我这样做时,所有属性都被序列化。但是通过@JsonView 过滤不再起作用了。

我无法修改 Page 对象,因为它是 Spring-data 对象。

我正在寻找一种方法来告诉杰克逊包含Page 对象的所有属性。

这是我的代码:

我的实体:

@Entity
@Table(name = "T_REGION")
public class Region implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "code", nullable = false)
    private Integer code;

    @Column(name = "name", length = 60, nullable = false)
    @JsonView(View.Summary.class)
    private String name;

    // Getters and setters
}

我的休息控制器:

@RestController
@RequestMapping("/api")
public class RegionResource {

    @RequestMapping(value = "/regionsearch1",
                method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)
    @JsonView(View.Summary.class)
    public ResponseEntity<Page<Region>> findAll1(
        @RequestParam(value = "page" , required = false) Integer offset,
        @RequestParam(value = "per_page", required = false) Integer limit,
        Sort sort)
        throws URISyntaxException {
        Pageable pageRequest = PaginationUtil.generatePageRequest(offset, limit, sort);
        Page<Region> page = regionRepository.findAll(pageRequest);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/regionsearch1", pageRequest);
        return new ResponseEntity<>(page, headers, HttpStatus.OK);
    }


    @RequestMapping(value = "/regionsearch2",
                method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)
    @JsonView(View.Summary.class)
    public ResponseEntity<List<Region>> findAll2(
        @RequestParam(value = "page" , required = false) Integer offset,
        @RequestParam(value = "per_page", required = false) Integer limit,
        Sort sort)
        throws URISyntaxException {
        Pageable pageRequest = PaginationUtil.generatePageRequest(offset, limit, sort);
        Page<Region> page = regionRepository.findAll(pageRequest);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/regionsearch2", pageRequest);
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

}

findAll1 返回:

[
  {
    "name": "Ile-de-France"
  },
  {
    "name": "Champagne-Ardenne"
  },
  ....
]

findAll2 返回:

{}

对象Page 的属性上没有@JsonView,因此没有属性被序列化。

即使使用了@JsonView,我也无法告诉杰克逊包含所有Page 属性。

有什么想法吗?

【问题讨论】:

  • 嗨,我遇到了同样的问题。所以我下载了最新版本的 Spring 源代码,然后我创建了界面,并使用 @JsonView(View.class) 修改了类 Page,然后我编译了它,最后,我创建了一个扩展类 View 以在我的项目中的 Spring MVC。试试吧,你会成功的:D
  • Spring Data Pagination returns no results with JSONView 重复。在那里可以找到更好的解决方案

标签: spring-mvc jackson spring-data-jpa jhipster


【解决方案1】:

另一种返回所有页面元素的方法是为Page接口创建自己的实现(包括你想要的JsonView):

JsonPage

public class JsonPage<T> extends org.springframework.data.domain.PageImpl<T> {

public JsonPage(final List<T> content, final Pageable pageable, final long total) {
    super(content, pageable, total);
}

public JsonPage(final List<T> content) {
    super(content);
}

public JsonPage(final Page<T> page, final Pageable pageable) {
    super(page.getContent(), pageable, page.getTotalElements());
}

@JsonView(JsonViews.UiView.class)
public int getTotalPages() {
    return super.getTotalPages();
}

@JsonView(JsonViews.UiView.class)
public long getTotalElements() {
    return super.getTotalElements();
}

@JsonView(JsonViews.UiView.class)
public boolean hasNext() {
    return super.hasNext();
}

@JsonView(JsonViews.UiView.class)
public boolean isLast() {
    return super.isLast();
}

@JsonView(JsonViews.UiView.class)
public boolean hasContent() {
    return super.hasContent();
}

@JsonView(JsonViews.UiView.class)
public List<T> getContent() {
    return super.getContent();
}
}

接下来将这个类返回给控制器层:

服务

@Override
public Page<User> findAll(final int page) {
    PageRequest pr = new PageRequest(page, pageSize, new Sort(Sort.Direction.DESC, "dateCreated"));
    return new JsonPage<User>(userRepository.findAll(pr), pr);
}

控制器

@JsonView(JsonViews.UiView.class)
@RequestMapping(method = RequestMethod.GET, value = "{page}")
public Page<User> getUsers(@PathVariable final int page) {
    return userService.findAll(page);
}

【讨论】:

  • 更好的答案,也想这样做
  • 很棒的解决方案。谢谢
  • 感谢这有很大帮助!
【解决方案2】:

我已经这样做了,效果很好


package com.natixis.spring.ws.configuration;
import java.io.IOException;
    
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.Page;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
    
@Configuration
public class JacksonAdapter extends WebMvcConfigurerAdapter {
    
    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        return new Jackson2ObjectMapperBuilder()
                .failOnUnknownProperties(false)
                .serializationInclusion(Include.NON_EMPTY)
                .serializerByType(Page.class, new JsonPageSerializer());
            
    }
    
    public class JsonPageSerializer extends JsonSerializer<Page<?>>{
    
        @Override
        public void serialize(Page<?> page, JsonGenerator jsonGen, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
            
            ObjectMapper om = new ObjectMapper()
                    .disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
                    .setSerializationInclusion(Include.NON_EMPTY);
            jsonGen.writeStartObject();
            jsonGen.writeFieldName("size");
            jsonGen.writeNumber(page.getSize());
            jsonGen.writeFieldName("number");
            jsonGen.writeNumber(page.getNumber());
            jsonGen.writeFieldName("totalElements");
            jsonGen.writeNumber(page.getTotalElements());
            jsonGen.writeFieldName("last");
            jsonGen.writeBoolean(page.isLast());
            jsonGen.writeFieldName("totalPages");
            jsonGen.writeNumber(page.getTotalPages());
            jsonGen.writeObjectField("sort", page.getSort());
            jsonGen.writeFieldName("first");
            jsonGen.writeBoolean(page.isFirst());
            jsonGen.writeFieldName("numberOfElements");
            jsonGen.writeNumber(page.getNumberOfElements());
            jsonGen.writeFieldName("content");
            jsonGen.writeRawValue(om.writerWithView(serializerProvider.getActiveView())
                    .writeValueAsString(page.getContent()));
            jsonGen.writeEndObject();
        }
           
    }
}

问候,

雷吉斯利马雷

【讨论】:

  • public class JsonPageSerializer extends JsonSerializer&gt;{ 的行不正确。我想你想要public class JsonPageSerializer extends JsonSerializer&lt;Page&gt; {
【解决方案3】:

我知道这是一个老问题,但您可以将这样的内容用于对象页面

@Configuration
public class JacksonAdapter implements WebMvcConfigurer {

    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        return new Jackson2ObjectMapperBuilder().failOnUnknownProperties(false).serializerByType(Page.class,
                new JsonPageSerializer());
    }

    public class JsonPageSerializer extends JsonSerializer<Page> {

        @Override
        public void serialize(Page page, JsonGenerator jsonGen, SerializerProvider serializerProvider)
                throws IOException {

            ObjectMapper om = new ObjectMapper().disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
            jsonGen.writeStartObject();
            jsonGen.writeFieldName("size");
            jsonGen.writeNumber(page.getSize());
            jsonGen.writeFieldName("number");
            jsonGen.writeNumber(page.getNumber());
            jsonGen.writeFieldName("totalElements");
            jsonGen.writeNumber(page.getTotalElements());
            jsonGen.writeFieldName("last");
            jsonGen.writeBoolean(page.isLast());
            jsonGen.writeFieldName("totalPages");
            jsonGen.writeNumber(page.getTotalPages());
            jsonGen.writeObjectField("sort", page.getSort());
            jsonGen.writeFieldName("first");
            jsonGen.writeBoolean(page.isFirst());
            jsonGen.writeFieldName("numberOfElements");
            jsonGen.writeNumber(page.getNumberOfElements());
            jsonGen.writeFieldName("content");
            jsonGen.writeRawValue(
                    om.writerWithView(serializerProvider.getActiveView()).writeValueAsString(page.getContent()));
            jsonGen.writeEndObject();
        }

    }
}

【讨论】:

    【解决方案4】:

    我遇到了同样的问题,我通过将 MapperFeature.DEFAULT_VIEW_INCLUSION 设置为 true 解决了这个问题,但是您应该在要应用视图的类中使用 JsonView 或 @ 注释 所有字段 987654323@ 注解,因此默认情况下它们不会包含在 json 中。

    【讨论】:

      猜你喜欢
      • 2011-08-11
      • 1970-01-01
      • 2015-10-30
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 2014-07-03
      • 2013-05-23
      • 1970-01-01
      相关资源
      最近更新 更多