将 epgsql 结果转换为 JSON

Converting epgsql results to JSON

总的来说,我是 Erlang 和函数式编程的初学者。为了好玩,为了让我开始,我正在转换现有的 Ruby Sinatra REST(ish) API 查询 PostgreSQL 和 returns JSON.

在 Erlang 方面,我使用 Cowboy、Epgsql 和 Jiffy 作为 JSON 库。

Epgsql returns 结果格式如下:

{ok, [{column,<<"column_name">>,int4,4,-1,0}], [{<<"value">>}]}

但 Jiffy 在编码为 JSON 时需要以下格式:

{[{<<"column_name">>,<<"value">>}]}

以下代码用于将 epgsql 输出转换为适合 jiffy 的输入:

假设 Data 是 Epgsql 输出,Key 是正在创建的 JSON 对象的名称:

{_, C, R} = Data,
Columns = [X || {_, X, _, _, _, _} <- C,
Rows = tuple_to_list(hd(R)),
Result = {[{atom_to_binary(Key, utf8), {lists:zip(Columns, Rows)}}]}.

但是,我想知道这是否是高效的 Erlang?

我查看了 Epgsql 和 Jiffy 的文档,但看不到任何更明显的执行转换的方法。

谢谢。

是的,需要解析。

例如函数解析结果

parse_result({error, #error{ code = <<"23505">>, extra = Extra }}) ->
    {match, [Column]} =
        re:run(proplists:get_value(detail, Extra),
               "Key \(([^\)]+)\)", [{capture, all_but_first, binary}]),
    throw({error, {non_unique, Column}});
parse_result({error, #error{ message = Msg }}) ->
    throw({error, Msg});
parse_result({ok, Cols, Rows}) ->
    to_map(Cols, Rows);
parse_result({ok, Counts, Cols, Rows}) ->
    {ok, Counts, to_map(Cols, Rows)};
parse_result(Result) ->
    Result.

然后函数将结果转换为映射

to_map(Cols, Rows) ->
    [ maps:from_list(lists:zipwith(fun(#column{name = N}, V) -> {N, V} end,
                                        Cols, tuple_to_list(Row))) || Row <- Rows ].

并将其编码为json。您可以更改我的代码并将输出作为 proplist。