You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postgres JSON/JSONB与Micronaut集成:JSON序列化异常问题

问题原因及解决方法

核心原因

  1. JDBC驱动的类型映射:PostgreSQL官方JDBC驱动会将json/jsonb类型字段、json_build_object函数的返回值,统一映射为org.postgresql.util.PGobject实例,而非Java标准的JSON对象(如Map、JsonNode)。
  2. Jackson默认序列化行为:Micronaut依赖Jackson处理JSON序列化,而Jackson对PGobject没有内置的序列化逻辑,会将其当作普通Java对象,直接序列化它的公共属性——type(存储PostgreSQL数据类型,如jsonb)、value(存储原始JSON字符串)、null(标记是否为NULL),最终就出现了你看到的嵌套结构。

解决方法

方法1:自定义Jackson序列化器

编写一个针对PGobject的序列化器,直接输出其value字段的原始JSON内容:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.postgresql.util.PGobject;
import java.io.IOException;

public class PGObjectJsonSerializer extends JsonSerializer<PGobject> {
    @Override
    public void serialize(PGobject pgObject, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (pgObject == null || pgObject.getValue() == null) {
            gen.writeNull();
            return;
        }
        // 直接写入原始JSON字符串,避免二次转义
        gen.writeRawValue(pgObject.getValue());
    }
}

然后在Micronaut中注册这个序列化器,比如在application.yml中配置:

jackson:
  serialization:
    modules:
      - com.yourpackage.serializers.PGObjectJsonSerializerModule

或者直接在实体类的对应字段上标注:

@JsonSerialize(using = PGObjectJsonSerializer.class)
private PGobject jsonData;

方法2:查询时转换为字符串并解析

在SQL查询中,将JSON类型的结果转为字符串,再在代码中解析为Java对象:

SELECT json_build_object('name', 'foo', 'age', 20)::text AS user_data FROM your_table;

在Repository方法中用String接收结果,再通过Jackson的ObjectMapper解析为Map或自定义DTO:

@Query("SELECT json_build_object('name', 'foo', 'age', 20)::text AS user_data FROM your_table")
String getUserDataAsString();

// 后续解析
Map<String, Object> userData = objectMapper.readValue(getUserDataAsString(), new TypeReference<>() {});

方法3:配置Micronaut Data类型转换

通过Micronaut Data的配置,自动将PGobject转换为JSON节点:
在application.yml中添加:

micronaut:
  data:
    jdbc:
      type-mapping:
        pgobject:
          json:
            target-type: com.fasterxml.jackson.databind.JsonNode

或者在实体类的JSON字段上添加@TypeDef注解(适用于Micronaut Data JPA):

@TypeDef(type = DataType.JSON)
private JsonNode jsonData;

内容的提问来源于stack exchange,提问作者Joel Sherriff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 22:13:19