web-dev-qa-db-ja.com

Spring Data PageはSortをJSONに正しくシリアライズしません

この問題は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);
    }
}

また、Java構成とXML構成を使用して、Spring Bootを使用しない単純なSpringアプリケーションを試しました。結果は同じです。

{
    "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
}

私はすべてを試したようですが、変更ログでソートの変更に関する通知が見つかりませんでした。SpringJIRAでそのような問題は見つかりませんでした。

したがって、問題は、次のような並べ替えでどのようにspring-data 2.X libs JSONを取得するかです。

"sort": [
    {
        "direction": "ASC",
        "property": "asdf",
        "ignoreCase": false,
        "nullHandling": "NATIVE",
        "ascending": true,
        "descending": false
    }
]

の代わりに:

"sort": {
    "sorted": true,
    "unsorted": false
}
14
Oleg Danyliuk

@ Oleg Danyliuk

私はあなたと同じ問題に遭遇し、あなたの返答は役に立ちましたが、ここで私は最も短い答えを提供します。


あなたが言ったように、Sortクラスのカスタムシリアライザを作成する必要があります

しかし、必要なのは、JsonSerializerクラス@JsonComponentジャクソンに登録します。


ソリューション

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;
    }
}

参照

8
Alexis Lavie

カスタムシリアライザを追加する問題を解決しました。

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()));
            }
        }
    }
}
4
Oleg Danyliuk