I’ve hit this a few times and had to remind myself how Postgres behaves when aggregating JSON columns or including them in ROW_TO_JSON
.
The short answer is that Postgres does the right thing. When a JSON column is included in ROW_TO_JSON
or JSON_AGG
the resulting values are not nested, encoded JSON.
Here’s our sample table with some data:
CREATE TABLE test (group_by text, config JSON); INSERT INTO test (group_by, config) VALUES ('one', '{"one":1}'::JSON) , ('one', '{"one":1}'::JSON) , ('two', '{"two":2}'::JSON) , ('two', '{"two":2}'::JSON) ;
Let’s try ROW_TO_JSON
first.
SELECT ROW_TO_JSON(test.*) example FROM test;
It’s easy to think that each row would be returned with the config
columns still JSON encoded, meaning we’d have to do something like this:
let row = someSqlClient('SELECT ROW_TO_JSON(test.*) example FROM test'); let example = JSON.parse(row.example); let config = JSON.parse(example.config);
That’s not the case. PostgreSQL does not nest encoded JSON, it instead puts everything into one level of JSON encoding.
example --------------------------------------- {"group_by":"one","config":{"one":1}} {"group_by":"one","config":{"one":1}} {"group_by":"two","config":{"two":2}} {"group_by":"two","config":{"two":2}}
The same is true for JSON_AGG
.
SELECT group_by, JSON_AGG(config) example FROM test GROUP BY group_by
example
comes out as a JSON array of objects.
group_by | example ----------+------------------------ two | [{"two":2}, {"two":2}] one | [{"one":1}, {"one":1}]