package com.ecep.contract.config; import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.Collection; import java.util.Collections; import org.hibernate.Hibernate; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.proxy.HibernateProxy; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import com.ecep.contract.model.IdentityEntity; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; /** * Jackson配置类,用于配置JSON序列化相关的设置,解决循环引用问题 */ @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.build(); // 关闭日期时间格式化输出为时间戳,而是输出为ISO格式的字符串 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 配置处理循环引用的策略,使用INDENT_OUTPUT格式化输出 objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 处理循环引用,启用引用处理功能 objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); // 配置Java 8时间模块的序列化格式 JavaTimeModule javaTimeModule = new JavaTimeModule(); // LocalDate javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE)); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE)); // LocalTime javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME)); javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME)); // LocalDateTime javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); objectMapper.registerModule(javaTimeModule); // 添加自定义模块,用于处理JPA/Hibernate代理对象 SimpleModule proxyModule = new SimpleModule("HibernateProxyModule"); // 添加代理对象序列化器,只输出ID字段 proxyModule.addSerializer(HibernateProxy.class, new HibernateProxySerializer()); // 使用BeanSerializerModifier来处理IdentityEntity类型,避免递归调用 proxyModule.setSerializerModifier(new BeanSerializerModifier() { @Override public JsonSerializer modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer serializer) { // 只对IdentityEntity类型进行修改 if (IdentityEntity.class.isAssignableFrom(beanDesc.getBeanClass()) && !HibernateProxy.class.isAssignableFrom(beanDesc.getBeanClass())) { return new IdentityEntitySerializer(serializer); } return serializer; } }); objectMapper.registerModule(proxyModule); return objectMapper; } /** * 专门用于处理Hibernate代理对象的序列化器 */ private static class HibernateProxySerializer extends StdSerializer { protected HibernateProxySerializer() { super(HibernateProxy.class); } @Override public void serialize(HibernateProxy value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 尝试初始化代理对象,如果未初始化则只输出ID try { Object unwrapped = value.getHibernateLazyInitializer().getImplementation(); // 检查是否为IdentityEntity实现类 if (unwrapped instanceof IdentityEntity) { gen.writeStartObject(); gen.writeNumberField("id", ((IdentityEntity) unwrapped).getId()); gen.writeEndObject(); } else { // 如果不是IdentityEntity,使用默认序列化 serializers.defaultSerializeValue(unwrapped, gen); } } catch (Exception e) { // 如果初始化失败,只输出ID if (value instanceof IdentityEntity) { gen.writeStartObject(); gen.writeNumberField("id", ((IdentityEntity) value).getId()); gen.writeEndObject(); } else { // 如果不是IdentityEntity,输出对象的基本信息 gen.writeStartObject(); gen.writeStringField("class", value.getClass().getName()); gen.writeEndObject(); } } } } /** * 用于处理集合类型的序列化器,避免懒加载集合在会话关闭时无法序列化的问题 */ private static class CollectionSerializer extends StdSerializer> { protected CollectionSerializer() { super((Class>) (Class) Collection.class); } @Override public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 检查集合是否为Hibernate的持久化集合 if (value instanceof PersistentCollection) { PersistentCollection persistentCollection = (PersistentCollection) value; // 如果集合未初始化,返回空集合 if (!persistentCollection.wasInitialized()) { gen.writeStartArray(); gen.writeEndArray(); return; } } // 如果已初始化,使用默认序列化 serializers.defaultSerializeValue(value, gen); } } /** * 用于处理IdentityEntity类型的序列化器包装器 */ private static class IdentityEntitySerializer extends StdSerializer { private final JsonSerializer delegate; protected IdentityEntitySerializer(JsonSerializer delegate) { super(Object.class); this.delegate = delegate; } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 对于IdentityEntity对象,如果未初始化,则只输出ID if (value instanceof IdentityEntity && !Hibernate.isInitialized(value)) { gen.writeStartObject(); gen.writeNumberField("id", ((IdentityEntity) value).getId()); gen.writeStringField("_proxy_", value.getClass().getName()); gen.writeEndObject(); } else { // 已初始化的实体,使用原始的序列化器进行序列化,避免递归调用 ((JsonSerializer) delegate).serialize(value, gen, serializers); } } } /** * 用于处理对象引用的序列化器,通过检测和管理对象引用避免循环引用问题 */ private static class IdentityReferenceSerializer extends StdSerializer { private final JsonSerializer delegate; private final ThreadLocal> visitedObjects = ThreadLocal .withInitial(java.util.HashSet::new); protected IdentityReferenceSerializer(JsonSerializer delegate) { super(Object.class); this.delegate = delegate; } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 处理null值 if (value == null) { serializers.defaultSerializeNull(gen); return; } java.util.Set visited = visitedObjects.get(); try { // 检查对象是否已经被访问过 if (visited.contains(value)) { // 如果对象实现了IdentityEntity,只输出ID if (value instanceof IdentityEntity) { gen.writeStartObject(); gen.writeNumberField("id", ((IdentityEntity) value).getId()); gen.writeStringField("_ref_", "" + ((IdentityEntity) value).getId()); gen.writeEndObject(); } else { // 对于非IdentityEntity对象,输出对象的toString或hashCode gen.writeString(value.toString()); } return; } // 标记对象为已访问 visited.add(value); // 使用委托序列化器进行正常序列化 ((JsonSerializer) delegate).serialize(value, gen, serializers); } finally { // 清理访问记录 visited.remove(value); if (visited.isEmpty()) { visitedObjects.remove(); } } } } }