0

Im using jackson-datatype-jsr310 module, which supports LocalDateTime serialization. but by default, it serializes date/time as "[2022,6,29,17,15,54]".

But I need to override this behaviour to serialize/deserialize it in "Calendar" format, ex. as json object

"arrivalDate": {
  "month": "JUNE",
  "dayOfWeek": "WEDNESDAY",
  "dayOfYear": 180,
  "nano": 0,
  "year": 2022,
  "monthValue": 6,
  "dayOfMonth": 29,
  "hour": 12,
  "minute": 53,
  "second": 46,
  "chronology": {
    "id": "ISO",
    "calendarType": "iso8601"
  }
}

The setting should be not global for all application, but only for specific ObjectMapper instantiation for internal purposes.

  • interesting, that it was working with Spring boot 2.2.6, but after upgrade to Sping Boot 2.5.5 default date serialization format changed and functionality is broken – Victor Mikhailov Jun 29 '22 at 15:34
  • 1
    What's stopping you from creating your own serializer/deserializer? – akortex Jun 29 '22 at 17:46

1 Answers1

0

Introduction

Let's consider Jackson 2.13.3 as the current version.

Analysis

Such feature seems to be absent out of the box

Please, see the following piece of source code and note the comment there: jackson-databind/BeanSerializerFactory.java at jackson-databind-2.13.3 · FasterXML/jackson-databind:

    protected JsonSerializer<?> _findUnsupportedTypeSerializer(SerializerProvider ctxt,
            JavaType type, BeanDescription beanDesc)
        throws JsonMappingException
    {
        // 05-May-2020, tatu: Should we check for possible Shape override to "POJO"?
        //   (to let users force 'serialize-as-POJO'?
        final String errorMsg = BeanUtil.checkUnsupportedType(type);

Maybe, it is worth opening the appropriate GitHub issue.

Possible workaround solution

Introduce and use a custom BeanSerializerFactory implementation that will not prevent using the default Jackson bean serializers for the JSR 310 types (the java.time package) and Joda types (the org.joda.time package).

To understand the idea, please, refer to the implementation of the methods:

  • com.fasterxml.jackson.databind.ser.BeanSerializerFactory._findUnsupportedTypeSerializer().
  • com.fasterxml.jackson.databind.util.BeanUtil.checkUnsupportedType().
  • com.fasterxml.jackson.databind.util.BeanUtil.isJava8TimeClass().

CustomBeanSerializerFactory class

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
import com.fasterxml.jackson.databind.ser.BeanSerializerFactory;

public final class CustomBeanSerializerFactory extends BeanSerializerFactory {
    protected CustomBeanSerializerFactory(final SerializerFactoryConfig config) {
        super(config);
    }

    @Override
    protected JsonSerializer<?> _findUnsupportedTypeSerializer(
        final SerializerProvider ctxt,
        final JavaType type,
        final BeanDescription beanDesc
    ) {
        return null;
    }
}

Schedule class

import java.time.LocalDateTime;

public final class Schedule {
    private final LocalDateTime arrivalDate;

    public Schedule(final LocalDateTime arrivalDate) {
        this.arrivalDate = arrivalDate;
    }

    public LocalDateTime getArrivalDate() {
        return arrivalDate;
    }
}

Program class

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;

public final class Program {
    public static void main(final String[] args) throws JsonProcessingException {
        final LocalDateTime localDateTime = LocalDateTime.of(
            2022, 1, 2, 3, 4, 5, 6
        );
        final Schedule schedule = new Schedule(localDateTime);

        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializerFactory(
            new CustomBeanSerializerFactory(null)
        );
        final String jsonString = objectMapper.writeValueAsString(schedule);
        System.out.println(jsonString);
    }
}

The program output:

{"arrivalDate":{"nano":6,"year":2022,"monthValue":1,"dayOfMonth":2,"hour":3,"minute":4,"second":5,"month":"JANUARY","dayOfWeek":"SUNDAY","dayOfYear":2,"chronology":{"id":"ISO","calendarType":"iso8601"}}}

Additional references