此问题出现在Spring-Data发行版2中。在最新版本1.13.9(及更早版本)中,它可以正常工作。
控制器代码:
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
@RequestMapping(value = "sorttest", method = RequestMethod.GET)
public Page<Integer> getDummy() {
return new PageImpl<>(Collections.singletonList(1), new PageRequest(0, 5, new Sort("asdf")), 1);
}
}
Spring-Data 2风格相同:
Pageable pageable = PageRequest.of(0, 10, new Sort(Sort.Direction.ASC, "asd"));
PageImpl<Integer> page = new PageImpl<Integer>(Lists.newArrayList(1,2,3), pageable, 3);
return page;
配置:
@SpringBootApplication
@EnableWebMvc
@EnableSpringDataWebSupport
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
还尝试了简单的Spring应用程序,没有带有Java配置的Spring Boot以及XML配置。结果是一样的:
{
"content": [
1
],
"pageable": {
"sort": {
"sorted": true,
"unsorted": false
},
"offset": 0,
"pageSize": 5,
"pageNumber": 0,
"paged": true,
"unpaged": false
},
"totalElements": 1,
"last": true,
"totalPages": 1,
"size": 5,
"number": 0,
"sort": {
"sorted": true,
"unsorted": false
},
"numberOfElements": 1,
"first": true
}
如果我将Spring-Data版本更改为1.X我正在为排序对象获得正确的JSON响应:
{
"content": [
1
],
"totalElements": 1,
"totalPages": 1,
"last": true,
"size": 5,
"number": 0,
"sort": [
{
"direction": "ASC",
"property": "asdf",
"ignoreCase": false,
"nullHandling": "NATIVE",
"ascending": true,
"descending": false
}
],
"numberOfElements": 1,
"first": true
}
似乎我尝试了所有内容,我没有在changelog中找到关于排序更改的任何通知,我在Spring JIRA中没有找到这样的问题。
所以问题是如何使用spring-data 2.X libs JSON进行排序,如:
"sort": [
{
"direction": "ASC",
"property": "asdf",
"ignoreCase": false,
"nullHandling": "NATIVE",
"ascending": true,
"descending": false
}
]
而不是:
"sort": {
"sorted": true,
"unsorted": false
}
答案 0 :(得分:5)
我遇到了与您相同的问题,发现您的回复非常有用,但我在这里提供了最简短的答案。
正如您所说,需要为Sort类创建自定义序列化程序。
但是,您只需使用 @JsonComponent
注释JsonSerializer类即可向杰克逊注册。
<强>解决方案强>
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.data.domain.Sort;
import java.io.IOException;
@JsonComponent
public class SortJsonSerializer extends JsonSerializer<Sort> {
@Override
public void serialize(Sort value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartArray();
value.iterator().forEachRemaining(v -> {
try {
gen.writeObject(v);
} catch (IOException e) {
e.printStackTrace();
}
});
gen.writeEndArray();
}
@Override
public Class<Sort> handledType() {
return Sort.class;
}
}
<强>参考强>
答案 1 :(得分:3)
我已经解决了添加自定义序列化器的问题:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.data.domain.Sort;
import java.io.IOException;
public class SortJsonSerializer extends JsonSerializer<Sort> {
@Override
public void serialize(Sort orders, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartArray();
orders.iterator().forEachRemaining(o -> {
try {
jsonGenerator.writeObject(o);
} catch (IOException e) {
e.printStackTrace();
}
});
jsonGenerator.writeEndArray();
}
@Override
public Class<Sort> handledType() {
return Sort.class;
}
}
为了让Spring使用它,我覆盖extendMessageConverters:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.xxx.ws"})
@EnableSpringDataWebSupport
public class SpringWebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
SortHandlerMethodArgumentResolver sortResolver = new SortHandlerMethodArgumentResolver();
// For sorting resolution alone
argumentResolvers.add(sortResolver);
PageableHandlerMethodArgumentResolver pageableResolver = new PageableHandlerMethodArgumentResolver(sortResolver);
pageableResolver.setMaxPageSize(10000);
// For sorting resolution encapsulated inside a pageable
argumentResolvers.add(pageableResolver);
argumentResolvers.add(new CurrentUserArgumentResolver());
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
SimpleModule module = new SimpleModule();
module.addSerializer(Sort.class, new SortJsonSerializer());
return new Jackson2ObjectMapperBuilder()
.findModulesViaServiceLoader(true)
.modulesToInstall(module);
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//First converters added in WebMvcConfigurationSupport.addDefaultHttpMessageConverters and then we add our behaviour here
Jackson2ObjectMapperBuilder builder = jackson2ObjectMapperBuilder();
for (int i=0; i<converters.size(); i++) {
if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
converters.set(i, new MappingJackson2HttpMessageConverter(builder.build()));
}
}
}
}