Search code examples
jsonspring-mvcjackson-databindlocaldate

Json mapper converts LocalDate to month, year, day of month etc


Json mapper converts LocalDate to month, year, day of month ... when converting java class to json like this,

"dob":{
  "year": 1992,
  "month": "MARCH",
  "dayOfMonth": 19,
  "dayOfWeek": "THURSDAY",
  "era": "CE",
  "dayOfYear": 79,
  "leapYear": true,
  "monthValue": 3,
  "chronology": {
    "calendarType": "iso8601",
    "id": "ISO"
  }
}

this is saved as a Date in mysql as 1992-03-19 how to return this date as it is like

"dob:1992-03-19"

Solution

  • Jackson and java.time types

    The Jackson JavaTimeModule is used to handle java.time serialization and deserialization.

    It provides a set of serializers and deserializers for the java.time types. If the SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled, java.time types will be serialized in standard ISO-8601 string representations.

    Handling serialization in your particular format

    However, once you have a very particular format, you can create a custom serializer:

    public class DateOfBirthSerializer extends JsonSerializer<LocalDate> {
    
        @Override
        public void serialize(LocalDate value, JsonGenerator gen,
                              SerializerProvider serializers) throws IOException {
            gen.writeString("dob:" + value.format(DateTimeFormatter.ISO_DATE));
        }
    }
    

    Then you can use it as follows:

    public class Foo {
    
        @JsonSerialize(using = DateOfBirthSerializer.class)
        private LocalDate dateOfBirth;
    
        // Getters and setters
    }
    

    Alternatively you can use:

    SimpleModule module = new SimpleModule();
    module.addSerializer(LocalDate.class, new DateOfBirthSerializer());
    
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(module);
    

    It will be applied to all LocalDate instances serialized with that ObjectMapper.

    Handling deserialization in your particular format

    For deserialization, you can use something like:

    public class DateOfBirthDeserializer extends JsonDeserializer<LocalDate> {
    
        @Override
        public LocalDate deserialize(JsonParser p,
                                     DeserializationContext ctxt) throws IOException {
    
            String value = p.getValueAsString();
            if (value.startsWith("dob:")) {
                value = value.substring(4);
            } else {
                throw ctxt.weirdStringException(value, 
                        LocalDate.class, "Value doesn't start with \"dob:\"");
            }
    
            return LocalDate.parse(value, DateTimeFormatter.ISO_DATE);
        }
    }