I wanted to know if there is any way to format a JSON in Oracle (as does this web site example)
In XML I used:
SELECT XMLSERIALIZE(Document XMLTYPE(V_RESPONSE) AS CLOB INDENT SIZE = 2)
INTO V_RESPONSE
FROM DUAL;
And it works very well.
With Oracle 12c, you can use the JSON_QUERY() function with the RETURNING ... PRETTY clause :
PRETTY : Specify PRETTY to pretty-print the return character string by inserting newline characters and indenting
Expression :
JSON_QUERY(js_value, '$' RETURNING VARCHAR2(4000) PRETTY)
Demo on DB Fiddle :
with t as (select '{"a":1, "b": [{"b1":2}, {"b2": "z"}]}' js from dual)
select json_query(js, '$' returning varchar2(4000) pretty) pretty_js, js from t;
Yields :
PRETTY_JS | JS
--------------------------|----------------------------------------
{ | {"a":1, "b": [{"b1":2}, {"b2": "z"}]}
"a" : 1, |
"b" : |
[ |
{ |
"b1" : 2 |
}, |
{ |
"b2" : "z" |
} |
] |
} |
When you're lucky enough to get to Oracle Database 19c, there's another option for pretty printing: JSON_serialize.
This allows you to convert JSON between VARCHAR2/CLOB/BLOB. And includes a PRETTY clause:
with t as (
select '{"a":1, "b": [{"b1":2}, {"b2": "z"}]}' js
from dual
)
select json_serialize (
js returning varchar2 pretty
) pretty_js,
js
from t;
PRETTY_JS JS
{ {"a":1, "b": [{"b1":2}, {"b2": "z"}]}
"a" : 1,
"b" :
[
{
"b1" : 2
},
{
"b2" : "z"
}
]
}
Related
I have a table with a json field with the following json:
[
{
productId: '1',
other : [
otherId: '2'
]
},
{
productId: '3',
other : [
otherId: '4'
]
}
]
I am trying to select the productId and otherId for every array element like this:
select JSON_EXTRACT(items, $.items[].productId) from order;
But this is completely wrong since it takes only the first element in the array
Do I need to write a loop or something?
First of all, the data you show is not valid JSON. It has multiple mistakes that make it invalid.
Here's a demo using valid JSON:
mysql> create table orders ( items json );
mysql> insert into orders set items = '[ { "productId": "1", "other": { "otherId": "2" } }, { "productId": "3", "other" : { "otherId": "4" } } ]'
mysql> SELECT JSON_EXTRACT(items, '$[*].productId') AS productIds FROM orders;
+------------+
| productIds |
+------------+
| ["1", "3"] |
+------------+
If you want each productId on a row by itself as a scalar value instead of a JSON array, you'd have to use JSON_TABLE() in MySQL 8.0:
mysql> SELECT j.* FROM orders CROSS JOIN JSON_TABLE(items, '$[*]' COLUMNS(productId INT PATH '$.productId')) AS j;
+-----------+
| productId |
+-----------+
| 1 |
| 3 |
+-----------+
This is tested in MySQL 8.0.23.
You also tagged your question MariaDB. I don't use MariaDB, and MariaDB has its own incompatible implementation of JSON support, so I can't predict how it will work.
Thanks for helping.
I have my table CONVERSATIONS structured in columns like this :
[ ID , JSON_CONTENT ]
In the column ID i have a simple id in Varchar
In the column JSON_CONTENT i something like this :
{
"id_conversation" : "25bc8cbffa8b4223a2ed527e30d927bf",
"exchanges": [
{
"A" : "...",
"B": "..."
},
{
"A" : "...",
"B": "..."
},
{
"A" : "...",
"Z" : "..."
}
]
}
I would like to query and get the id and the last element of exchanges :
[ ID , LAST_ELT_IN_EXCHANGE_IN_JSON_CONTENT]
I wanted to do this :
select TOP 3 ID, JSON_QUERY(JSON_CONTENT, '$.exchange[-1]')
from CONVERSATION
But of course Transact SQL is not Python.
I saw theses answers, but i don't know how to applicate to my problem.
Select last value from Json array
Thanks for helping <3
If I understand you correctly, you need an additional APPLY operator and a combination of OPENJSON() and ROW_NUMBER(). The result from the OPENJSON() call is a table with columns key, value and type and when the JSON content is an array, the key column returns the index of the element in the specified array:
Table:
SELECT ID, JSON_CONTENT
INTO CONVERSATION
FROM (VALUES
(1, '{"id_conversation":"25bc8cbffa8b4223a2ed527e30d927bf","exchanges":[{"A":"...","B":"..."},{"A":"...","B":"..."},{"A":"...","Z":"..."}]}')
) v (ID, JSON_CONTENT)
Statement:
SELECT c.ID, j.[value]
FROM CONVERSATION c
OUTER APPLY (
SELECT [value], ROW_NUMBER() OVER (ORDER BY CONVERT(int, [key]) DESC) AS rn
FROM OPENJSON(c.JSON_CONTENT, '$.exchanges')
) j
WHERE j.rn = 1
Result:
ID value
------------------------
1 {
"A" : "...",
"Z" : "..."
}
Notice, that -1 is not a valid array index in your path expression, but you can access the item in a JSON array by index (e.g. '$.exchanges[2]').
I have a Parameters_A column in table A which has data like this :
Number,3771|ScheduleTime,0.00:00:00|LastData,|DP_AddPaymentDetails_URL,NULL|DP_URL,https://facebook.com
I need to move it into Parameters_B column in table B with foreign key (ID_A) from table A like this:
[
{
"Name":"Number",
"Value":"3771"
},
{
"Name":"ScheduleTime",
"Value":"0.00:00:00"
},
{
"Name":"LastData",
"Value":""
},
{
"Name":"DP_AddPaymentDetails_URL",
"Value":"NULL"
},
{
"Name":"DP_URL",
"Value":"https://facebook.com"
}
]
JSON is just a string. Assuming the input has no single or double quotes, you can convert it to a JSON string in any SQL Server version. To do so you need to replace :
, with ", "Value":"
| with "},{"Name":"
Add [{"Name":" at the front and
"}] at the end
to get a proper JSON string.
This query :
select
'[{"Name":"' +
replace(
replace('Number,3771|ScheduleTime,0.00:00:00|LastData,|DP_AddPaymentDetails_URL,NULL|DP_URL,https://facebook.com',',','", "Value":"')
,'|','"},{"Name":"')
+'"}]'
Produces :
[{"Name":"Number", "Value":"3771"},{"Name":"ScheduleTime", "Value":"0.00:00:00"},{"Name":"LastData", "Value":""},{"Name":"DP_AddPaymentDetails_URL", "Value":"NULL"},{"Name":"DP_URL", "Value":"https://facebook.com"}]
After formatting :
[
{"Name":"Number", "Value":"3771"},
{"Name":"ScheduleTime", "Value":"0.00:00:00"},
{"Name":"LastData", "Value":""},
{"Name":"DP_AddPaymentDetails_URL", "Value":"NULL"},
{"Name":"DP_URL", "Value":"https://facebook.com"}
]
Parsing this to extract individual values though requires SQL Server 2016 and later
I have a Json data stored in SQL server:
{
"group":{
"operator":"AND",
"rules":[
{
"condition":"=",
"field":"F1",
"table":"ATT",
"data":"TEST",
"readOnly":false,
"hidden":false,
"$$hashKey":"005"
},
{
"condition":"=",
"field":"CLASS",
"table":"OBJ",
"data":"A1",
"readOnly":false,
"hidden":false,
"$$hashKey":"008"
},
{
"group":{
"operator":"AND",
"rules":[
{
"condition":"=",
"field":"F1",
"table":"ATT",
"data":"TEST2",
"readOnly":false,
"hidden":false,
"$$hashKey":"00D"
},
{
"condition":"=",
"field":"F1",
"table":"ATT",
"data":"TEST3",
"readOnly":false,
"hidden":false,
"$$hashKey":"00G"
}
]
},
"table":"",
"$$hashKey":"009"
}
]
}
}
How can I get the count of the element field having value =F1 using SQL?
DECLARE #json NVARCHAR(MAX) = '{"group":{
"operator":"AND",
"rules":
[{"condition":"=",
"field":"F1",
"table":"ATT",
"data":"TEST",
"readOnly":false,
"hidden":false,
"$$hashKey":"005"},
{"condition":"=",
"field":"BANKID",
"table":"ATT",
"data":"A1",
"readOnly":false,
"hidden":false,
"$$hashKey":"008"}]}}';
SELECT COUNT(*)
FROM OPENJSON(#json, '$.group.rules')
WHERE JSON_VALUE(value, '$.field') = 'F1'
You have a table, you say? CROSS APPLY is your friend:
SELECT T.[data], rules.F1_count
FROM T CROSS APPLY (
SELECT COUNT(*) AS F1_count
FROM OPENJSON(jsonData, '$.group.rules')
WHERE JSON_VALUE(value, '$.field') = 'F1'
) AS rules
Try this ->
Select Count(*)
From mytable
WHERE JSON_VALUE(Serialized, '$.field')="F1"
As an advice JSON data should not be stored it self. You should make tables and columns depending on the data you are storing. Maybe make a database called group, with a table called operator, which would have three columns, operator, rule and rule value. So it would look something like this:
Operator Rule RuleValue
-------- ----------- ---------
| #1 | condition | = |
| #1 | field | f1 |
| #1 | table | ATT |
| #2 | data | test |
You can change the table to your needs but remember JSON and XML is a way of storing data in files. So when storing data in database, you shouldn't store it in XMl or JSON
I'm trying to do select * from demo where demojson->'sub'->'item' = array("") but this doesn't work. I'd like to find the following
All rows where .sub.item in the JSON column is an array containing exactly one empty string ([""])
All rows where .sub.item in the JSON column is an array that may contain more than one item, but at least one of the items is an empty string. (["not empty", "also not empty", ""])
demojson column could contain for example
{
"key": "value",
"sub": {
"item": [""]
}
}
Have you tried
SELECT * from demo
WHERE demojson->'sub'->>'item' = '[""]';
Here ->> operator allows to get JSON object field as text.
And another solution
SELECT * from demo
WHERE json_array_length(demojson->'sub'->'item') = 1 AND
demojson->'sub'->'item'->>0 = '';
Here ->> operators allows to get JSON first array element as text.
Due JSONLint doesn't validate the supplied text example, I've used the next:
CREATE TABLE info (id int, j JSON);
insert into info values
(1, '{"key":"k1", "sub": {"item":["i1","i2"]}}'),
(2, '{"key":"k2", "sub": {"item":[""]}}'),
(3, '{"key":"k3", "sub": {"item":["i2","i3"]}}');
Using the where clause in this way, it works:
select * from info
where j->'sub'->>'item' = '[""]';
+----+------------------------------------+
| id | j |
+----+------------------------------------+
| 2 | {"key":"k2", "sub": {"item":[""]}} |
+----+------------------------------------+
Can check it here: http://rextester.com/VEPY57423
Try the following:
SELECT * FROM demo
WHERE demojson->'sub'->'item' = to_jsonb(ARRAY['']);