1. Introduction

This post would demo how to do custom JSON serialization in SpringBoot apps(Spring MVC or RESTful service). By default, SpringBoot uses jackson to serialize objects. For example:

If we have this object:

public class MyBean {
    private int id;
    private String name;

    private Date bornDate;

    //getters and setters
    ...
}

And the above object is returned by a SpringBoot Restful service like this:

@RestController
public class MyController {

    @RequestMapping(value="/myBean")
    public @ResponseBody
    MyBean myBean()  {
        MyBean result =  new MyBean();
        result.setId(1);
        result.setName("Jackson");
        result.setBornDate(new Date());
        return result;
    }
}

We run the SpringBoot app and visit http://localhost:8080/myBean, then we would get this result:

{"id":1,"name":"Jackson","bornDate":1561531639483}

The bornDate field is a Long literal, what if we want it to be in format MM-dd-yyyy HH:mm:ss,just like this:

{"id":1,"name":"Jackson","bornDate":"06-26-2019 06:47:19"}

How to do this job?

2. Environments

  • SpringBoot 1.x and 2.x

3. Ways to do this job

3.1 use @JsonFormat

You can just use the @JsonFormat to specify the pattern of the field to do custom serialization, just as follows:

public class MyBean {
    private int id;
    private String name;

    @JsonFormat(pattern = "MM-dd-yyyy HH:mm:ss")
    private Date bornDate;

    //getters and setters
    ...
}

3.2 use custom JsonSerializer

the @JsonFormat can only change the field with this annotation, if you want to permernantly change the serialization of some type, you can just define a custom JsonSerializer.

First define a custom JsonSerializer by extending the JsonSerializer:

public class CustomDateSerializer extends JsonSerializer<Date> {
    private static SimpleDateFormat formatter
            = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss");

    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(formatter.format(date));
    }
}

Then ,add this custom serializer to ObjectMapper:

@Configuration
public class JacksonConfig {
    @Bean
    @Primary
    public ObjectMapper serializingObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(Date.class, new CustomDateSerializer()); //change all Date object's json serialization
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
}

4. The @JsonSerialize(using = CustomDateSerializer.class) problem

If we use the @JsonSerialize(using = CustomDateSerializer.class), we would get this error:

{"Map":{"timestamp":1561369998555,"status":500,"error":"Internal Server Error","message":"No converter found for return value of type: class com.bswen.sbmvc.domain.MyBean","path":"/myBean"}}%  

It seems that this annotation is not supported by SpringBoot anymore, just be careful.

5. Summary

The example source code has been uploaded to github, you can visit here to view the example source codes.