sqljsonpostgresql

Create JSON object from array of keys and values where values are JSON objects


A table (in fact a view which is already the result of some JSON aggregation) has a column of keys, and a column of values that are in JSON format:

+-----------+------------------------------------------------------------+
| user_id   | user_data_json                                             |
+-----------+------------------------------------------------------------+
| daveb1985 | {lastlogin:1732605022730, posts_read:[18, 23, 45], etc...} |
| trish2003 | {lastlogin:1732604033135, posts_read:[101], etc...}        |
| q2342rte  | {lastlogin:1731302284832, posts_read:[], etc...}           |
+-----------+------------------------------------------------------------+

I would like to return a JSON object like this:

{
    daveb1985: {
        lastlogin: 1732605022730,
        posts_read: [18, 23, 45]
    },
    trish2003: {
        lastlogin: 1732604033135,
        posts_read: [101]
    },
    q2342rte: {
        lastlogin: 1731302284832,
        posts_read: []
    }
}

The function json_object ( keys text[], values text[] ) → json, combined with array_agg is close to what I want, but it requires the values to be text, whereas my values have type JSON.

I can cast the values to text, but then object values are strings, not JSON objects, which are cumbersome to return to JSON in the client:

  SELECT
    json_object(
      array_agg(user_id), array_agg(CAST(user_data_json AS TEXT))
    ) AS result
  FROM userpostsjson;

Is there any way to construct the JSON object directly?


Solution

  • You are looking for the json_object_agg or jsonb_object_agg function, which creates a single object (per grouping) using a key-value pair.

    SELECT
      jsonb_object_agg(upj.user_id, upj.user_data_json)
    FROM userpostsjson upj;
    

    db<>fiddle