Jackson序列化POJO时Object类型属性异常显示问题求助
问题原因
这个问题本质是Hibernate懒加载代理导致的。当你用java.lang.Object类型映射Postgres的JSON字段时,Hibernate会给该字段生成懒加载代理对象(比如PersistentBag这类代理类),而非直接返回实际的JSON数据对象。Jackson序列化时会直接处理这个代理对象,把它的内部状态属性(traversableAgain、empty)序列化出来,自然就看不到真实的JSON内容了。
改用ObjectNode能正常序列化,是因为Hibernate不会给ObjectNode生成懒加载代理——它属于Jackson的明确JSON节点类型,Hibernate会直接映射存储的JSON数据到该类型,没有代理层干扰。
解决方案:通过ObjectMapper配置解决
完全可以通过配置Jackson的ObjectMapper来处理,有几种实用方案:
1. 引入Jackson Hibernate模块自动处理代理
添加Jackson针对Hibernate的适配模块(比如jackson-datatype-hibernate5,对应Hibernate5版本),然后在ObjectMapper中注册该模块,它会自动识别Hibernate代理对象,序列化时穿透代理获取真实数据:
ObjectMapper mapper = new ObjectMapper(); Hibernate5Module hibernateModule = new Hibernate5Module(); // 强制加载懒加载对象,需确保序列化时Hibernate Session处于打开状态 hibernateModule.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING); mapper.registerModule(hibernateModule);
如果不想强制加载(担心Session关闭导致懒加载异常),也可以提前在查询时通过fetch join或@Fetch(FetchMode.EAGER)注解加载该字段,再配合模块的默认配置即可。
2. 自定义序列化器处理代理对象
如果不想引入额外模块,可以给problematicProperty字段写个自定义序列化器,手动识别Hibernate代理并获取真实对象:
public class HibernateProxyObjectSerializer extends JsonSerializer<Object> { @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 判断是否为Hibernate代理对象 if (value instanceof HibernateProxy) { HibernateProxy proxy = (HibernateProxy) value; // 获取代理背后的真实对象 Object actualData = proxy.getHibernateLazyInitializer().getImplementation(); gen.writeObject(actualData); } else { gen.writeObject(value); } } }
然后在POJO的字段上添加注解绑定序列化器:
@JsonSerialize(using = HibernateProxyObjectSerializer.class) private Object problematicProperty;
3. 禁用该字段的懒加载(Hibernate层面配置)
在实体类的problematicProperty字段上添加@Fetch(FetchMode.EAGER)注解,强制Hibernate查询时直接加载该字段的真实JSON数据,避免生成代理对象。这种方式从根源上消除了代理干扰,Jackson序列化自然就能拿到真实内容。
内容的提问来源于stack exchange,提问作者Marko D

