PageImpl JSON serialization with Spring Boot 2

Posted at — Jun 10, 2018
Riekpil logo
Learn how to test real-world applications with the Testing Spring Boot Applications Masterclass. Comprehensive online course with 8 modules and 130+ video lessons to master well-known Java testing libraries: JUnit 5, Mockito, Testcontainers, WireMock, Awaitility, Selenium, LocalStack, Selenide, and Spring's Outstanding Test Support.

During the migration of a Spring Boot application from 1.5.13 to 2.0.2, some of my Spring Rest Docs tests started failing. The reason being that some of my RestController s return a org.springframework.data.domain.PageImpl object (from Spring Data Commons).

@RestController
public class MyRestController {

    @GetMapping
    public PageImpl<SomeDtoObject> listAll() {
        ...
    }
}

With Spring Boot 1.5.13, this results in JSON like this:

{
  "content": [
    {
      ...
    },
    {
      ...
    },
    ....
  ],
  "totalElements": 50,
  "totalPages": 3,
  "last": false,
  "size": 20,
  "number": 0,
  "numberOfElements": 1,
  "first": true,
  "sort": [
    {
      "direction": "DESC",
      "property": "date",
      "ignoreCase": false,
      "nullHandling": "NATIVE",
      "ascending": false,
      "descending": true
    }
  ]
}

However, with Spring Boot 2.0.2 (which includes Spring Data Commons 2.0.7), the resulting JSON is quite different:

{
  "content": [
    {
      ...
    },
    {
      ...
    },
    ....
  ],
  "pageable": {
    "sort": {
      "sorted": true,
      "unsorted": false
    },
    "offset": 0,
    "pageNumber": 0,
    "pageSize": 20,
    "paged": true,
    "unpaged": false
  },
  "totalPages": 3,
  "last": false,
  "totalElements": 50,
  "size": 20,
  "number": 0,
  "numberOfElements": 1,
  "sort": {
    "sorted": true,
    "unsorted": false
  },
  "first": true
}

The content element is still there, but the others are quite different.

In order to have the same back as before, add a custom JSON serializer:

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.PageImpl;
import org.springframework.data.domain.Sort;
import java.io.IOException;

@JsonComponent
public class PageImplJacksonSerializer extends JsonSerializer<PageImpl<?>> {

    @Override
    public void serialize(PageImpl page, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

        jsonGenerator.writeStartObject();
        jsonGenerator.writeObjectField("content", page.getContent());
        jsonGenerator.writeBooleanField("first", page.isFirst());
        jsonGenerator.writeBooleanField("last", page.isLast());
        jsonGenerator.writeNumberField("totalPages", page.getTotalPages());
        jsonGenerator.writeNumberField("totalElements", page.getTotalElements());
        jsonGenerator.writeNumberField("numberOfElements", page.getNumberOfElements());

        jsonGenerator.writeNumberField("size", page.getSize());
        jsonGenerator.writeNumberField("number", page.getNumber());

        Sort sort = page.getSort();

        jsonGenerator.writeArrayFieldStart("sort");

        for (Sort.Order order : sort) {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("property", order.getProperty());
            jsonGenerator.writeStringField("direction", order.getDirection().name());
            jsonGenerator.writeBooleanField("ignoreCase", order.isIgnoreCase());
            jsonGenerator.writeStringField("nullHandling", order.getNullHandling().name());
            jsonGenerator.writeEndObject();
        }

        jsonGenerator.writeEndArray();
        jsonGenerator.writeEndObject();
    }
}

Spring Boot will automatically pick this up (Due to the @JsonComponent annotation) to serialize the PageImpl objects.

 

If you want to be notified in the future about new articles, as well as other interesting things I'm working on, join my mailing list!
I send emails quite infrequently, and will never share your email address with anyone else.