I'm pretty green in my Postgres experience so I hope this isn't too remedial :)
If nested JSON is passed as a variable in PostgreSQL, can it be parsed without first dumping it into a temporary table?
Let's say I wanted to get the mother's names from the sample below. What would the SELECT statement look like?
do
$$
declare persons json =
'{
"name":"Sally",
"spouse":
{
"name":"Alex",
"parents":
{
"father":"Rafael",
"mother":"Ofelia"
},
"phones":
[
{
"type":"work",
"number":"619-555-1212"
},
{
"type":"cell",
"number":"012-345-6789"
}
]
}
}';
begin
/* ??? */
end;
$$
Many thanks in advance,
Matt
It can be parsed, but the question is what will you do with the response?
If you just want to see it in the results, then the quickest is to define your json in a CTE:
with p as (
select '{
"name":"Sally",
"spouse":
{
"name":"Alex",
"parents":
{
"father":"Rafael",
"mother":"Ofelia"
},
"phones":
[
{
"type":"work",
"number":"619-555-1212"
},
{
"type":"cell",
"number":"012-345-6789"
}
]
}
}'::jsonb as persons
)
select persons->'spouse'->'parents'->>'mother'
from p;
?column?
----------
Ofelia
(1 row)
Related
Currently I am generating some jsons with data with oracle for backend purposes and I'm struggling with complex and repetetive structions that I have to process manually.
For example I have this array of objects:
{
"infoColumnsWidgets": [
{
"widgetNamespace": "mot",
"widgetName": "info_column",
"orderNumber": 1,
"navigateToPage": null,
"widgetData": {
"title": "Fact",
"textPattern": "$v0",
"values": [
{
"id": "v0",
"type": "int",
"value": "200000"
}
]
}
},
{
"widgetNamespace": "mot",
"widgetName": "info_column",
"orderNumber": 2,
"navigateToPage": null,
"widgetData": {
"title": "Plan",
"textPattern": "$v0",
"values": [
{
"id": "v0",
"type": "int",
"value": "200000"
}
]
}
},
{
"widgetNamespace": "mot",
"widgetName": "info_column",
"orderNumber": 3,
"navigateToPage": null,
"widgetData": {
"title": "Prognosis",
"textPattern": "$v0",
"values": [
{
"id": "v0",
"type": "int",
"value": "100"
}
]
}
}
]
}
Certainly I generate it in a loop but this structure occurs often and I'd prefer to put it into some function to do the following:
function f_getTest return clob as
v_res clob;
begin
apex_json.initialize_clob_output;
apex_json.open_object;
apex_json.open_object('infoColumnsWidgets');
for rec in (select * from some_table_data)
loop
apex_json.write_raw(f_getWidgetJson(rec.param));
end loop;
apex_json.close_object;
apex_json.close_all;
v_res := apex_json.get_clob_output;
apex_json.free_output;
return v_res;
end;
But as far as I know there is no option to put one json into another using apex_json. I can try with some weird workarounds with putting some placeholders and replacing them in final clob but no, I don't want, please, don't make me do that.
Any ideas are super welcome
Does this help ? I took the example from oracle-base and moved the body code into a separate procedure. In the example below it is an inline procedure but nothing stops you from putting into a standalone procedure or a package.
DECLARE
PROCEDURE dept_object
IS
l_cursor SYS_REFCURSOR;
BEGIN
OPEN l_cursor FOR
SELECT d.dname AS "department_name",
d.deptno AS "department_number",
CURSOR(SELECT e.empno AS "employee_number",
e.ename AS "employee_name"
FROM emp e
WHERE e.deptno = d.deptno
ORDER BY e.empno) AS "employees"
FROM dept d
ORDER BY d.dname;
APEX_JSON.open_object;
APEX_JSON.write('departments', l_cursor);
APEX_JSON.close_object;
END;
BEGIN
APEX_JSON.initialize_clob_output;
dept_object;
DBMS_OUTPUT.put_line(APEX_JSON.get_clob_output);
APEX_JSON.free_output;
END;
/
I'm after running into some trouble parsing a set of JSON documents using SQL Server 2017.
I've encountered a nested array (sample below) within a document which uses dynamic ObjectId's i.e. 123 as the object Key as opposed to using a static key i.e. Category and then having a separate key:value to ref the ObjectId.
As a result I can't extract the items to a table using the regular CROSS APPLY OPENJSON syntax without specifying each individual Object Id (there are thousands)?
Is there a way to do this without referencing each ObjectId explicitly ideally i'd like to return all product items in a table and just have a field withe the categoryId.
"ProductItems": {
"123": [
{
"item": "13663"
}
]
"124": [
{
"value": "2336"
},
{
"value": "3667"
}
],
"453": [
{
"value": "8667"
},
{
"value": "1956"
}
]
}
Try something like this:
DECLARE #x NVARCHAR(MAX)=
'{"ProductItems":{
"123": [
{
"item": "13663"
}
],
"124": [
{
"value": "2336"
},
{
"value": "3667"
}
],
"453": [
{
"value": "8667"
},
{
"value": "1956"
}
]
}}'
SELECT j2.*, j3.* FROM OPENJSON(#x) j1
CROSS APPLY OPENJSON(j1.Value) j2
CROSS APPLY OPENJSON(j2.Value) j3
I have the following JSON and i need to query only the name property values.
DECLARE #j NVARCHAR(4000) = N'{
"ArrayValue":[
{
"name": "XXX",
"value": 10
},
{
"name": "Memory123",
"value": 20
}
]
}'
Following is what i get with OPENJSON()
SELECT value as Name
FROM OPENJSON(#j, '$.ArrayValue')
Whcih will get the following output.
Name
---------------------------------------------------
{ "name": "Memory" }
{ "name": "Memory123" }
However I need the output in the following format.
Name
-----
Memory
Memory123
Is there any simpler way without using replace?
You can define ArrayValue as a JSON column, then use CROSS APPLY to get the name values. Here's an example:
DECLARE #j NVARCHAR(4000) = N'{
"ArrayValue":[
{
"name": "XXX",
"value": 10
},
{
"name": "Memory123",
"value": 20
}
]
}'
SELECT b.name
FROM OPENJSON(#j)
WITH (ArrayValue NVARCHAR(MAX) AS JSON) AS a
CROSS APPLY OPENJSON(a.ArrayValue)
WITH ([name] NVARCHAR(100)) AS b
I have the following JSON
{
"eventSummaryList": [
{
"customer": "189256",
"data": "{\"cliente\":\"189256\",\"data_posicao\":\"1491426372\",\"gps_valido\":\"1\",\"horimetro\":\"120561\",\"ibuttonHex\":\"0\",\"ibuttonPart1\":\"0\",\"ibuttonPart2\":\"0\",\"id_evento\":\"null\",\"id_motorista\":\"0\",\"ignicao\":\"1\",\"latitude\":\"-2222222\",\"longitude\":\"-2222222\",\"odometro\":\"253692\",\"pos_memoria\":\"0\",\"veiculo\":\"44444\",\"velocidade\":\"50\"}",
"identifierEventRule": "77404",
"identifierRule": "6",
"identifierSummary": "28901976",
"rule": "velocidade_maior_que",
"status": 1,
"vehicle": "44444"
}
],
"header": {
"mensagem": {
"estilo": "SUCCESS",
"mensagem": "Successfully executed service",
"plataforma": "EVENT_POINT",
"status": "SUCESSO"
}
}
}
And I need to extract the value "velocidade" what's inside "data" that
contains another json.
I'm using the following syntax but it returns null.
select cast((value::json ->'data')::json->> 'velocidade' AS int) AS velocidade,
Try:
SELECT ((value::json #>> '{eventSummaryList,0,data}')::json ->> 'velocidade')::int
(The #>> or ->> operators are the key. If you use #> or ->, you'll end up with a json-encoded json string. BTW this is really a messed up model, I would look into fixing its input first/instead.)
http://rextester.com/THVYFK9026
I have some JSON along the following lines, the format of which cannot, unfortunately, be changed:
{
"elements": {
"nodes": [
{
"data": {
"name": "Name here",
"color": "#FFFFFF",
"id": "n0"
}
}
]
}
}
This is stored in a postgres database and I'd like to pull out records by means of the id embedded in the JSON above. So far I've tried stuff like this:
SELECT "data".* FROM "data" WHERE payload #>> '{elements,nodes,data,id}' = 'n0';
...without success; although this query runs it returns nothing. Can anyone suggest how this might be done?
Create schema:
create table json (
id serial primary key,
data jsonb
);
insert into json (data) values (
'{ "elements": {
"nodes": [
{
"data": {
"name": "Name here",
"color": "#FFFFFF",
"id": "n0"
}
}
]
}
}
'::jsonb);
Query itself:
select * from json js,jsonb_array_elements(data->'elements'->'nodes') as node
where node->'data'->>'id' = 'n0';