【问题标题】:How to serialize Java8 LocalDateTime to json as calendar object using Jackson如何使用 Jackson 将 Java8 LocalDateTime 序列化为 json 作为日历对象
【发布时间】:2022-07-01 13:50:03
【问题描述】:

我正在使用支持 LocalDateTime 序列化的 jackson-datatype-jsr310 模块。 但默认情况下,它将日期/时间序列化为“[2022,6,29,17,15,54]”。

但我需要重写此行为以以“日历”格式对其进行序列化/反序列化,例如。作为json对象

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

该设置不应该对所有应用程序都是全局的,而应仅用于内部目的的特定 ObjectMapper 实例化。

【问题讨论】:

  • 有趣的是,它与 Spring boot 2.2.6 一起工作,但在升级到 Sping Boot 2.5.5 后,默认日期序列化格式发生了变化并且功能被破坏了
  • 是什么阻止您创建自己的序列化器/反序列化器?

标签: java json serialization jackson jsr310


【解决方案1】:

简介

让我们将 Jackson 2.13.3 视为当前版本。

可能的解决方法

引入并使用自定义的 BeanSerializerFactory 实现,该实现不会阻止对 JSR 310 类型(java.time 包)和 Joda 类型(org.joda.time 包)使用默认的 Jackson bean 序列化程序。

要理解这个想法,请参考方法的实现:

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

CustomBeanSerializerFactory

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

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

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

程序输出:

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

其他参考

【讨论】:

    最近更新 更多