出于各种原因,我正在创建一个应用程序,该应用程序将SQL查询字符串作为URL参数,并将其传递给Postgres(类似于CartDB SQL API和CFPB的Qu)。然后,Rails呈现来自Postgres的结果的JSON响应。
我的控制器中的代码段:
@table = ActiveRecord::Base.connection.execute(@query)
render json: @table
这很好。但是,当我使用Postgres JSON函数(row_to_json,json_agg)时,它将嵌套的JSON属性呈现为字符串。例如,以下查询:
query?q=SELECT max(municipal) AS series, json_agg(row_to_json((SELECT r FROM (SELECT sch_yr,grade_1 AS value ) r WHERE grade_1 IS NOT NULL))ORDER BY sch_yr ASC) AS values FROM ed_enroll WHERE grade_1 IS NOT NULL GROUP BY municipal
返回:
{
series: "Abington",
values: "[{"sch_yr":"2005-06","value":180}, {"sch_yr":"2005-06","value":180}, {"sch_yr":"2006-07","value":198}, {"sch_yr":"2006-07","value":198}, {"sch_yr":"2007-08","value":158}, {"sch_yr":"2007-08","value":158}, {"sch_yr":"2008-09","value":167}, {"sch_yr":"2008-09","value":167}, {"sch_yr":"2009-10","value":170}, {"sch_yr":"2009-10","value":170}, {"sch_yr":"2010-11","value":153}, {"sch_yr":"2010-11","value":153}, {"sch_yr":"2011-12","value":167}, {"sch_yr":"2011-12","value":167}]"
},
{
series: "Acton",
values: "[{"sch_yr":"2005-06","value":353}, {"sch_yr":"2005-06","value":353}, {"sch_yr":"2006-07","value":316}, {"sch_yr":"2006-07","value":316}, {"sch_yr":"2007-08","value":323}, {"sch_yr":"2007-08","value":323}, {"sch_yr":"2008-09","value":327}, {"sch_yr":"2008-09","value":327}, {"sch_yr":"2009-10","value":336}, {"sch_yr":"2009-10","value":336}, {"sch_yr":"2010-11","value":351}, {"sch_yr":"2010-11","value":351}, {"sch_yr":"2011-12","value":341}, {"sch_yr":"2011-12","value":341}]"
}
因此,它仅部分呈现JSON,当我在查询中嵌套使用Postgres函数创建的JSON数组时,就会遇到问题。
我不确定从哪里开始这个问题。有任何想法吗?我确信这是Rails的问题。
ActiveRecord::Base.connection.execute
不知道如何将数据库类型分解为Ruby类型,因此从中得到的所有内容(数字,布尔值,JSON,所有内容)都是字符串。如果您想从控制器中获取明智的JSON,则必须手动将@table
中的数据转换为Ruby类型,然后以常规方式将Ruby格式的数据转换为JSON。
您的@table
实际上将是PG::Result
实例,并且这些实例具有诸如PG::Result
(获取列类型)和ftype
(获取列的类型修饰符)之类的方法,可以帮助您确定哪种排序方式数据位于ftype
的每一列中。您可能会要求fmod
作为每一列的类型和修饰符,然后将它们交给fmod
PostgreSQL函数以获得一些可理解的类型字符串。然后将这些类型的字符串映射到转换方法,然后使用该映射来解包返回的字符串。如果深入研究ActiveRecord源,您将看到AR做类似的事情。虽然AR源代码不适合胆怯的人,对不起,但是当您走出应如何与数据库进行AR事物的狭窄界限时,这是正确的做法。
[您可能想重新考虑一下“ SQL的笨拙”方法。如果您能找到一种自己构建SQL的方法,则可能会更轻松(并且在查询时可以将其列入白名单)。
PG::Result
类(@table的类型),利用PG::Result
将结果值类型转换为红宝石对象。对于您的示例,可以如下使用format_type
:
format_type