List in a nested json in mariaDB with json_table - json

I can't get the data from a nested json using json_table
My MariaDB server is 10.6.0
set #json='
{
"id":"9696e1ac-e173-4905-ac51-c47c0ef8c90b",
"username":"demo#demo.com",
"firstName":"DEMO",
"lastName":"DEMO",
"email":"demo#demo.com",
"isEnabled":true,
"attributes":{
"ASSOCIATED_COMPANY":"CLCORP001,CLCORP002,CLCORP003,CLCORP004,PECORP001,PECORP002,PECORP003,PECORP004,PECORP005,DECORP001",
"ROLES":"[\"Super Admin\",\"Admin\",\"Executive\"]",
},
}';
I tried this but it doesn't work
SELECT
*
FROM
SELECT * FROM json_table(#json, '$.*' COLUMNS(NESTED PATH '$.attributes.ROLES[*]' COLUMNS (roles varchar(250) PATH '$'))) roles
TEXT PATH '$'))) roles

No matter if MySQL or MariaDB: If your json string is not valid, json_object will always fail.
In both MySQL and MariaDB you can use json_valid() function to check your json:
set #json='
{
"id":"9696e1ac-e173-4905-ac51-c47c0ef8c90b",
"username":"demo#demo.com",
"firstName":"DEMO",
"lastName":"DEMO",
"email":"demo#demo.com",
"isEnabled":true,
"attributes":{
"ASSOCIATED_COMPANY":"CLCORP001,CLCORP002,CLCORP003,CLCORP004,PECORP001,PECORP002,PECORP003,PECORP004,PECORP005,DECORP001",
"ROLES":"[\"Super Admin\",\"Admin\",\"Executive\"]",
},
}';
SELECT JSON_VALID(#json);
+-------------------+
| JSON_VALID(#json) |
+-------------------+
| 0 |
+-------------------+
On success JSON_VALID will return 1.
I didn't check in detail, but looks like the extra quotation marks in attributes.ROLES are not allowed.

Related

Can't get through mysql JSON_CONTAINS to show the correcct data. Getting null everytime i try

The data in the table events with column attributes is in json and looks like this -
{"event_volunteer_requests":{"1":{"volunteertypeid":250,"volunteer_needed_count":50,"cc_email":""},"2":{"volunteertypeid":249,"volunteer_needed_count":30,"cc_email":""}}}
So the context is that i want to show the events with volunteertypeid present in the attributes. There are many volunteers., this is just sample data.
I've been using the query below
SELECT
*
FROM `events`
WHERE `zoneid` = 27
AND `isactive` = 1
AND JSON_CONTAINS(`attributes` -> '$.event_volunteer_requests[*].volunteertypeid', '249');
I just can't make this work and i've scorched the internet for hours. Any guidance would be appreciated.
Your JSON structure uses object syntax ({"key": "value"}), but you seem to want to use it as a JSON array (["value", "value", ...]).
The [*] syntax in JSON paths works for JSON arrays, not for JSON objects.
If your JSON document must be nested object syntax:
{
"event_volunteer_requests": {
"1": {
"cc_email": "",
"volunteertypeid": 250,
"volunteer_needed_count": 50
},
"2": {
"cc_email": "",
"volunteertypeid": 249,
"volunteer_needed_count": 30
}
}
}
Then you can do what you want this way:
SELECT t.id, t.volunteertypeid
FROM (
SELECT j.id, JSON_EXTRACT(a.attributes, CONCAT('$.event_volunteer_requests."', j.id, '".volunteertypeid')) AS volunteertypeid
FROM (SELECT '{"event_volunteer_requests":{"1":{"volunteertypeid":250,"volunteer_needed_count":50,"cc_email":""},"2":{"volunteertypeid":249,"volunteer_needed_count":30,"cc_email":""}}}' as attributes) AS a
CROSS JOIN JSON_TABLE(JSON_KEYS(a.attributes, '$.event_volunteer_requests'), '$[*]' COLUMNS (id INT PATH '$')) AS j
) AS t
WHERE t.volunteertypeid = 249;
Result:
+------+-----------------+
| id | volunteertypeid |
+------+-----------------+
| 2 | 249 |
+------+-----------------+
The JSON_TABLE() function requires MySQL 8.0. If you use MySQL 5.7, you must upgrade.

MySQL Parse and Split JSON value

I have a column which contains a JSON value of different lengths
["The Cherries:2.50","Draw:3.25","Swansea Jacks:2.87"]
I want to split them and store into a JSON like so:
[
{
name: "The Cherries",
odds: 2.50
},
{
name: "Draw",
odds: 3.25
},
{
name: "Swansea",
odds: 2.87
},
]
What I did right now is looping and splitting them in the UI which to me is quite heavy for the client. I want to parse and split them all in a single query.
If you are running MySQL 8.0, you can use json_table() to split the original arrayto rows, and then build new objects and aggregate them with json_arrayagg().
We need a primary key column (or set of columns) so we can properly aggreate the generated rows, I assumed id:
select
t.id,
json_arrayagg(json_object(
'name', substring(j.val, 1, locate(':', j.val) - 1),
'odds', substring(j.val, locate(':', j.val) + 1)
)) new_js
from mytable t
cross join json_table(t.js, '$[*]' columns (val varchar(500) path '$')) as j
group by t.id
Demo on DB Fiddle
Sample data:
id | js
-: | :-------------------------------------------------------
1 | ["The Cherries:2.50", "Draw:3.25", "Swansea Jacks:2.87"]
Query results:
id | new_js
-: | :----------------------------------------------------------------------------------------------------------------------
1 | [{"name": "The Cherries", "odds": "2.50"}, {"name": "Draw", "odds": "3.25"}, {"name": "Swansea Jacks", "odds": "2.87"}]
You can use json_table to create rows from the json object.
Just replace table_name with your table name and json with the column that contains json
SELECT json_arrayagg(json_object('name',SUBSTRING_INDEX(person, ':', 1) ,'odds',SUBSTRING_INDEX(person, ':', -1) ))
FROM table_name,
JSON_TABLE(json, '$[*]' COLUMNS (person VARCHAR(40) PATH '$') people;
Here is a Db fiddle you can refer
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=801de9f067e89a48d45ef9a5bd2d094a

Extracting value using common_schema not working for nested JSON

I have a DB field called data of type is MEDIUMTEXT, which stores values in JSON format. I'm using extract_json_value method from common_schema.
When JSON is not nested, it works fine. For example, when applications_data table's data field is
{
"key": "value"
}
This query works fine:
SELECT data into #json from applications_data;
SELECT common_schema.extract_json_value(#json, 'key') as result;
and gives result: key
However, when the data field is a nested JSON, it fails. For example, JSON is:
{
"key": {
"overview": "sample"
}
}
Using the same query as above and result is empty, not NULL:
Remember:
extract_json_value
...
This function internally relies on json_to_xml(): it first
converts the JSON data to XML, then uses ExtractValue to apply
XPath.
...
and
ExtractValue(xml_frag, xpath_expr)
...
If no matching text node is found for the expression (including the
implicit /text())—for whatever reason, as long as xpath_expr is valid, and xml_frag consists of elements which are properly nested and closed—an empty string is returned. No distinction is made between a match on an empty element and no match at all. This is by design.
If you need to determine whether no matching element was found in
xml_frag or such an element was found but contained no child text
nodes, you should test the result of an expression that uses the XPath
count() function.
...
Test:
mysql> SET #`json` := '
'> {
'> "key": {
'> "overview": "sample"
'> }
'> }
'> ';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT
-> common_schema.extract_json_value(#`json`, 'key') AS result0,
-> common_schema.extract_json_value(#`json`, count('key')) AS result1,
-> common_schema.extract_json_value(#`json`, 'key/overview') AS result2,
-> common_schema.extract_json_value(#`json`, count('key/overview')) AS result3;
+---------+---------+---------+---------+
| result0 | result1 | result2 | result3 |
+---------+---------+---------+---------+
| | 1 | sample | 1 |
+---------+---------+---------+---------+
1 row in set (0.03 sec)

SQL Server JSON_VALUE syntax

I created a SQL Server Table with 25 columns. One of my columns is actually JSON text, stored as nvarchar(max).
Now I need to able to query this JSON column and parse out the various attributes. I have tried applying JSON_VALUE to my column but am doing something wrong; my query runs but returns NULL for all the values.
The JSON itself looks like:
[
{
"lineName":"GHjr",
"pipeDiameter":"12",
"pipeLength":"52000",
"pressure":"15",
"volume":"107"
},
{
"lineName":"Ks3R",
"pipeDiameter":"9",
"pipeLength":"40000",
"pressure":"15",
"volume":"80"
}
]
The SQL I am using is:
select
DOC_ID, LINE_SPECS,
JSON_VALUE(LINE_SPECS, '$.lineName') as line_name,
JSON_VALUE(LINE_SPECS, '$.pipe_Diameter') as diameter
from dbo.MY_TEST_DOCS
where ISJSON(LINE_SPECS) > 0
and len(LINE_SPECS) > 3
However, my 2 "parsed" columns are returning all NULL. How do I parse the five attributes from this column?
Without the [] ISJSON is returning false
With [] ISJSON retuns true
Without the [] JSON_VALUE returns NULLs
With [] JSON_VALUE returns values
dbfddle.uk has sql server 2016 available....
create table test (LINE_SPECS nvarchar(max));
insert into test values (N'
{
"lineName":"GHjr",
"pipeDiameter":"12",
"pipeLength":"52000",
"pressure":"15",
"volume":"107"
},
{
"lineName":"Ks3R",
"pipeDiameter":"9",
"pipeLength":"40000",
"pressure":"15",
"volume":"80"
}
');
select *
from test
where ISJSON(LINE_SPECS) > 0
;
GO
| LINE_SPECS |
| :--------- |
select
JSON_VALUE(LINE_SPECS, '$.lineName') as line_name
, JSON_VALUE(LINE_SPECS, '$.pipeDiameter') as diameter
from test
;
GO
line_name | diameter
:-------- | :-------
GHjr | 12
dbfiddle here

Reading JSON from MEMSQL

Having a problem with JSON / MEMSQL. Here's my table:
CREATE TABLE `MEMSQLPOLYGLOT` (
ID BIGINT AUTO_INCREMENT,
`DATA` JSON NULL,
PRIMARY KEY (ID)
);
Here's the record I'm trying to read:
insert into MEMTEST (DATA) values
('
{
"EnterpriseMessage" :
{
"Body" :
[
{
"AccountNumber":"ABCD",
"AdminCompany":null,
"BrokerNumber":"WWonka"
},
{
"AccountNumber":"CSNE",
"AdminCompany":null,
"BrokerNumber":"ZWiza"
}
],
"Header" :
{
"mimetye":"application/vnd.ms-powerpoint",
"destinationsystem":"ETL",
"requiresack":"FALSE",
"SimpArr":
[
"BYTS6181",
"EVU98124",
"Genesys"
],
"EmptyFile":1
}
}
}
');
I can read the SimpArr array in the header.
SELECT DATA::EnterpriseMessage::Header::SimpArr from MEMTEST;
Returns:
["BYTS6181","EVU98124","Genesys"]
I can also pass in a key index to get a specific value, such as:
select JSON_EXTRACT_JSON(DATA::EnterpriseMessage::Body, 1) from MEMTEST;
This returns the 2nd value of the SimpArr since it's a zero-based index.
I can also read the array of objects in the Body:
select JSON_EXTRACT_JSON(DATA::EnterpriseMessage::Body, 0) from MEMTEST;
which returns the first object in that array:
{
"AccountNumber":"ABCD",
"AdminCompany":null,
"BrokerNumber":"WWonka"
}
However, I am unable to find a way to read the individual attributes of this object.
Anyone have any ideas?
You can just pass the key as an extra argument to JSON_EXTRACT_JSON:
mysql> select JSON_EXTRACT_JSON(DATA::EnterpriseMessage::Body, 0, "AccountNumber") from MEMTEST;
+----------------------------------------------------------------------+
| JSON_EXTRACT_JSON(DATA::EnterpriseMessage::Body, 0, "AccountNumber") |
+----------------------------------------------------------------------+
| "ABCD" |
+----------------------------------------------------------------------+
1 row in set (0.08 sec)
JSON_EXTRACT_JSON takes any number of arguments, either string keys or integer array indices. For example, we can unroll the :: syntax in your example above:
select JSON_EXTRACT_JSON(DATA, "EnterpriseMessage", "Body", 0, "AccountNumber") from MEMTEST;
Also note that the return value has double quotes in it. That's because you extract JSON, and the JSON representation of a string has double quotes. If you actually want to get the string, use JSON_EXTRACT_STRING:
mysql> select JSON_EXTRACT_STRING(DATA, "EnterpriseMessage", "Body", 0, "AccountNumber") from MEMTEST;
+----------------------------------------------------------------------------+
| JSON_EXTRACT_STRING(DATA, "EnterpriseMessage", "Body", 0, "AccountNumber") |
+----------------------------------------------------------------------------+
| ABCD |
+----------------------------------------------------------------------------+
1 row in set (0.07 sec)