Convert rows into json object in postgresql - json

With PostgreSQL 13 I'm trying to convert rows with 2 columns into a JSON object where a column value is the key and the other column is the value.
My table:
key | value
-------- | --------
key1 | value1
key2 | value2
key3 | value3
My expected result:
{"key1":"value1","key2":"value2","key3":"value3"}
I found the json_object function on postgresql website : PostgreSQL JSON functions but I can't get it to work.
I tried with other functions:
SELECT jsonb_agg(jsonb_build_object(key ,value))
FROM mytable
but it gives me an array of json objects
[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"}]
I know I can still build it with string functions but I feel like it's an easy task even if I can't get it :-/
Any help would be appreciated !

You can use jsonb_object_agg()
select jsonb_object_agg(key, value)
from the_table

Related

how to create Json object of each column in a row

i have a table itemmaster in Postgresql.
id| attribute1 | attribute2 | attribute3
1 | Good | Average | Best
i want output as json like
[{"attribute1":"Good"},{"attribute2":"Average"},{"attribute3":"Best"}]
i want to use this JSON as nested JSON other object, ihave tried row_to_json and json object builder but not getting exact result.
select json_build_array(json_build_object('attribute1', itemmaster.attribute1),
json_build_object('attribute2', itemmaster.attribute2),
json_build_object('attribute3', itemmaster.attribute3))
from itemmaster;

Query mysql json column array using AND NOT CONTAINS (mysql 5.7)

I have a table with a json column that contains an array of objects, like the following:
create table test_json (json_id int not null primary key, json_data json not null) select 1 as json_id, '[{"category":"circle"},{"category":"square", "qualifier":"def"}]' as json_data union select 2 as json_id, '[{"category":"triangle", "qualifier":"xyz"},{"category":"square"}]' as json_data;
+---------+----------------------------------------------------------------------------------------+
| json_id | json_data |
+--------------------------------------------------------------------------------------------------+
| 1 | [{"category":"circle"}, {"category":"square", "qualifier":"def"}] |
| 2 | [{"category":"triangle", "qualifier":"xyz"}, {"category":"square"}] |
+---------+----------------------------------------------------------------------------------------+
I'd like to be able to query this table to look for any rows (json_id's) that contain a json object in the array with both a "category" value of "square" and no "qualifier" property.
The sample table above is just a sample and I'm looking for a query that would work over hundreds of rows and hundreds of objects in the json array.
In MySQL 8.0, you would use JSON_TABLE() for this:
mysql> select json_id, j.* from test_json, json_table(json_data, '$[*]' columns (
category varchar(20) path '$.category',
qualifier varchar(10) path '$.qualifier')) as j
where j.category = 'square' and j.qualifier is null;
+---------+----------+-----------+
| json_id | category | qualifier |
+---------+----------+-----------+
| 2 | square | NULL |
+---------+----------+-----------+
It's not clear why you would use JSON for this at all. It would be better to store the data in the normal manner, one row per object, with category and qualifier as individual columns.
A query against normal columns is a lot simpler to write, and you can optimize the query easily with an index:
select * from mytable where category = 'square' and qualifier is null;
I found another solution using only MySQL 5.7 JSON functions:
select json_id, json_data from test_json
where json_extract(json_data,
concat(
trim(trailing '.category' from
json_unquote(json_search(json_data, 'one', 'square'))
),
'.qualifier')
) is null
This assumes the value 'square' only occurs as a value for a "category" field. This is true in your simple example, but I don't know if it will be true in your real data.
Result:
+---------+------------------------------------------------------------------------+
| json_id | json_data |
+---------+------------------------------------------------------------------------+
| 2 | [{"category": "triangle", "qualifier": "xyz"}, {"category": "square"}] |
+---------+------------------------------------------------------------------------+
I still think that it's a CodeSmell anytime you reference JSON columns in a condition in the WHERE clause. I understood your comment that this is a simplified example, but regardless of the JSON structure, if you need to do search conditions, your queries will be far easier to develop if your data is stored in conventional columns in normalized tables.
Your request is not clear. Both of your SQL records has not such properties but your JSON object has. Maybe you try to find any record that has such object. So the following is your answer:
create table test_json (json_id int not null primary key, json_data json not null) select 1 as json_id, '[{"category":"circle", "qualifier":"abc"},{"category":"square", "qualifier":"def"}]' as json_data union select 2 as json_id, '[{"category":"triangle", "qualifier":"xyz"},{"category":"square"}]' as json_data;
select * from test_json;
select * from test_json where 'square' in (JSON_EXTRACT(json_data, '$[0].category'),JSON_EXTRACT(json_data, '$[1].category'))
AND (JSON_EXTRACT(json_data, '$[0].qualifier') is NULL || JSON_EXTRACT(json_data, '$[1].qualifier') is NULL);
See Online Demo
Also see JSON Function Reference

How to regexp in MySql json string

Let's assume this users table:
-----------------------------------------
| id | ... | info |
-----------------------------------------
| 1 | ... | {"items":["132","136"]} |
I need to make a request to fetch users that have items with id == 136.
This following is the sql I built but it does not work and I dont understand why:
SELECT _u.id FROM users _u WHERE _u.info REGEXP '("items":)([)("136")(])'
Thank you in advance!
Here is one approach using the MySQL JSON functions:
SELECT *
FROM yourTable
WHERE JSON_SEARCH(JSON_EXTRACT(json, "$.items"), 'one', "136") IS NOT NULL;
Demo
The call to JSON_EXTRACT first extracts the JSON array under the items key. Then, we use JSON_SEARCH to try to find an element "136".
Edit:
If you are certain that the JSON to be searched would always just be one key items along with a single level JSON array, then REGEXP might be viable here:
SELECT *
FROM yourTable
WHERE json REGEXP '"items":\\[.*"136".*\\]';
Demo

Count number of objects in JSON array stored as Hive string column

I have a Hive table with a JSON string stored as a string in a column.
Something like this.
Id | Column1 (String)
1 | [{k1:v1,k2:v2},{k3:v3,k4:v4}]
2 | [{k1:v1,k2:v2}]
I want to count the number of JSON objects in the column.
Id | Count
1 | 2
2 | 1
What would be the query to achieve this?
If the JSON objects are such simple structs without nested structs then you can split by '}' and use size()-1:
size(split(column,'[}]'))-1
It works with empty strings correctly, NULLs require special handling if you need to convert to 0:
case when column is null then 0 else size(split(column,'[}]'))-1 end

build JSON object with dynamic keys and json values

I am attempting to build a JSON object with a postgres query. The output I'm looking for is similar to the object below. The properties "xxx" and "yyy" come from a column as do the dates.
{
"xxx": [ "2018-07-26T11:42:04.514Z", "2018-07-26T11:52:04.514Z"],
"yyy": [ "2018-07-26T05:42:09.210Z", "2018-07-26T07:22:04.024Z"]
}
I was hoping to do this with a query similar to the one below:
SELECT
json_object(
array_agg(name),
array_agg(json_build_array(start_date, end_date)
)
FROM my_table
The my_table table would look roughly like this:
name | start_date | end_date |
-------------------------------------------------------------
xxx | 2018-07-26T11:42:04.514Z | 2018-07-26T11:52:04.514Z |
yyy | 2018-07-26T05:42:09.210Z | 2018-07-26T07:22:04.024Z |
However, json_object only accepts text arrays and I can't seem to find an alternative. So, I get ERROR: function json_object(text[], json[]) does not exist. Thanks for reading!
Use jsonb_build_array() and json_object_agg().
select json_object_agg(name, jsonb_build_array(start_date, end_date))
from my_table
DbFiddle.