JFinal+Postgresql使用Json类型返回的问题

示例:

表A  id, name

表B  id, a_id, tag

一(A)对多(B)关联查询,相关联的B表使用聚合函数合并未json数组

SELECT T.ID,
       T.NAME,
       array_to_json ( T.tag_array ) 
FROM
	(
	SELECT A.ID,
	       A.NAME,
		( SELECT ARRAY_AGG ( b.tag ) FROM b b WHERE b.a_id = A.ID ) tag_array 
	FROM A A 
	) T

采用 Db.find 返回List<Record> 列表,返回前端json数据。


但是问题来了。返回的结果如下:

{
    "id": "1",
    "name": "测试1",
    "tag_array":{
         "type": "json",
         "value": "[\"标签1\",\"标签2\"]"
     }
}

即结果会把json类型的tag_array转为对象,且自动补了两个key(type,value),并把json数组给转成了一个json数组字符串

而预想要的结果为:

{
    "id": "1",
    "name": "测试1",
    "tag_array":[
        "标签1",
        "标签2"
     ]
}

使用Record接收返回值好像会把postgresql的json类型当作一个对象处理。

请问如果解决这种需求有什么好的解决方案,

  1. 查询A表,遍历A取B 然后封装最终结果,这种如果数据量大的话需要频繁请求数据库根据A表id查B表关联数据。

  2. 使用聚合函数,业务层对结果遍历二次装配,总感觉比较繁琐且损耗一定性能(目前采用这种)


评论区

JFinal

2018-12-15 17:17

其实这个问题,jfinal 完全没有干预过, 都是 JDBC 返回的数据的样子

如果你希望干预一下,可以通过继承 ModelBuilder 与 RecordBuilder 这两个类,假定你扩展出来的类为: MyModelBuilder、MyRecordBuilder,注入到 PostDialect 中去:
postgresqlDialect.setModelBuilder(new MyModelBuilder());
postgresqlDialect.setModelBuilder(new MyRecordBuilder());
arp.setDialect( postgresqlDialect);

在 MyModelBuilder、MyRecordBuilder 里头,细致地控制一下从 JDBC 返回的数据可以了

azzcsimp

2018-12-15 17:36

@JFinal 谢谢波总提供的方案,看了下两个Builder的代码,解决思路应该是判断返回字段的数据类型做干预处理,不过要先知道json类型对应的类型值,有空研究一下,谢谢。

zhangtianxiao

2019-01-10 23:28

这个东西.. 我很早就搞定了, 也分享过, 后来文章让我删掉了...

左右冷静

2019-06-24 22:27

解决方法实际上很简单,不需要那么复杂:
第一步:
public static class PGObjectSerializer implements ObjectSerializer {
public final static PGObjectSerializer instance = new PGObjectSerializer();
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
if(object!=null)
serializer.out.write(object.toString());
else
serializer.out.writeNull();
}
}
第二步:
SerializeConfig.getGlobalInstance().put(PGobject.class, PGObjectSerializer.instance);