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
相关产品推荐
相关产品推荐

