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

Quarkus3.9.1+Java21:PostgreSQL原生查询JSON列返回JSON对象的方法

解决Quarkus中JSON类型列返回字符串而非JSON对象的问题

问题根源

你当前使用原生SQL查询(createNativeQuery),这种方式会直接返回数据库原始列值,绕过了Hibernate为User实体配置的@JdbcTypeCode(SqlTypes.JSON)映射逻辑,所以address字段以JSON字符串形式返回,而非自动解析后的Map对象。

最优解决方案:改用实体查询(JPQL/Panache API)

直接查询User实体,让Hibernate自动处理JSON列的映射,步骤如下:

1. 修改Service层代码

替换原生SQL查询为Panache内置方法或JPQL查询:

package org.acme;

import jakarta.enterprise.context.ApplicationScoped;
import java.util.List;

@ApplicationScoped
public class UserService {
    // 直接使用Panache的内置查询方法,无需EntityManager
    public List<User> getUser() {
        return User.listAll();
    }

    // 或者用JPQL查询(如果需要自定义条件)
    // public List<User> getUser() {
    //     return em.createQuery("SELECT u FROM User u", User.class).getResultList();
    // }
}

2. 修改Controller层返回类型

明确返回List<User>,让Jackson正确序列化实体:

package org.acme;

import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;

@Path("/api")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class GreetingResource {
    @Inject
    UserService userService;

    @POST
    @Path("/usr")
    public List<User> getUsers() {
        return userService.getUser();
    }
}

备选方案:原生SQL下手动解析JSON字符串

如果必须使用原生SQL(比如复杂多表查询),可以借助Jackson手动将JSON字符串解析为Map:

修改Service层代码

package org.acme;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@ApplicationScoped
public class UserService {
    @Inject
    EntityManager em;
    @Inject
    ObjectMapper objectMapper;

    public List<Map<String, Object>> getUser() {
        String sql = "SELECT user_id, name, address FROM user_test";
        Query q = em.createNativeQuery(sql);
        List<Object[]> results = q.getResultList();
        
        return results.stream().map(row -> {
            Map<String, Object> userMap = new HashMap<>();
            userMap.put("userId", row[0]);
            userMap.put("name", row[1]);
            
            // 手动解析JSON字符串为Map
            try {
                Map<String, String> address = objectMapper.readValue(
                    (String) row[2], 
                    new TypeReference<Map<String, String>>() {}
                );
                userMap.put("address", address);
            } catch (Exception e) {
                throw new RuntimeException("解析地址JSON失败", e);
            }
            
            return userMap;
        }).collect(Collectors.toList());
    }
}

效果验证

修改后API响应会变成:

[
    {
        "userId": 2,
        "name": "John Doe",
        "address": {
            "zip": "98765",
            "city": "Springfield",
            "street": "1234 Oak St"
        }
    }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 12:52:47