Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create json with column values as object keys

I have a table defined like this:

CREATE TABLE data_table AS (
  id bigserial,
  "name" text NOT NULL,
  "value" text NOT NULL,
  CONSTRAINT data_table_pk PRIMARY KEY (id)
);

INSERT INTO data_table ("name", "value") VALUES
('key_1', 'value_1'),
('key_2', 'value_2');

I would like to get a JSON object from this table content, which will look like this:

{
  "key_1":"value_1",
  "key_2":"value_2"
}

Now I'm using the client application to parse the result set into JSON format. Is it possible to accomplish this by a postgresl query?

like image 550
Przemek Avatar asked Jul 15 '14 10:07

Przemek


People also ask

Can a JSON key be an object?

JSON cannot be an object. JSON is a string format. The data is only JSON when it is in a string format. When it is converted to a JavaScript variable, it becomes a JavaScript object.

What is the difference between Jsonb and JSON?

The json data type stores an exact copy of the input text, which processing functions must reparse on each execution; while jsonb data is stored in a decomposed binary format that makes it slightly slower to input due to added conversion overhead, but significantly faster to process, since no reparsing is needed.

What is Jsonb column?

The JSONB data type stores JSON (JavaScript Object Notation) data as a binary representation of the JSONB value, which eliminates whitespace, duplicate keys, and key ordering. JSONB supports GIN indexes.

Can Jsonb be an array?

jsonb elements can be of the following types: Objects. Arrays. String.


2 Answers

In a generic scenario you can nest more than one json_object_agg functions on top of a subquery. The inner subqueries should always have at least one column that will be used by outer subquery as keys for the json_object_agg function.

In the example, in the subquery C the values of the column action are used as keys in the subquery A. In A the values of column role are used as keys in query A.

-- query A
select json_object_agg(q1.role, q1.actions) from (
-- subquery B
    select q2.role, json_object_agg(q2.action, q2.permissions) as actions from (
-- subquery C
        select r.name as role, a.name as action, json_build_object (
            'enabled', coalesce(a.bit & bit_and(p.actionids) <> 0, false), 
            'guestUnsupported', r.name = 'guest' and a."guestUnsupported"
        ) as permissions
        from role r
        left join action a on a.entity = 'route'
        left join permission p on p.roleid = r.id 
          and a.entity = p.entityname 
          and (p.entityid = 1 or p.entityid is null)
        where
        1 = 1
        and r.enabled
        and r.deleted is null
        group by r.name, a.id
    ) as q2 group by q2.role
) as q1

The result is a single row/single column with the following content:

{
    "Role 1": {
        "APIPUT": {
            "enabled": false,
            "guestUnsupported": false
        },
        "APIDELETE": {
            "enabled": false,
            "guestUnsupported": false
        },
        "APIGET": {
            "enabled": true,
            "guestUnsupported": false
        },
        "APIPOST": {
            "enabled": true,
            "guestUnsupported": false
        }
    },
    "Role 2": {
        "APIPUT": {
            "enabled": false,
            "guestUnsupported": false
        },
        "APIDELETE": {
            "enabled": false,
            "guestUnsupported": false
        },
        "APIGET": {
            "enabled": true,
            "guestUnsupported": false
        },
        "APIPOST": {
            "enabled": false,
            "guestUnsupported": false
        }
    }
}
like image 153
sandro Avatar answered Sep 29 '22 11:09

sandro


If you're on 9.4 you can do the following:

$ select json_object_agg("name", "value") from data_table;
           json_object_agg
----------------------------------------------
{ "key_1" : "value_1", "key_2" : "value_2" }
like image 37
steevel Avatar answered Sep 29 '22 13:09

steevel