Extracting data from JSON field in Redshift - json

I am trying to extract some data from a JSON field.
[{"id": 10001, "person1": {"name": "Kevin", "role": "junior"},
"person2": {"name": "Scott", "role": "senior"}}]
I am trying to extract the name and role under each ID.
I tried the below but it returned empty record.
SELECT json_extract_path(column_name::json,'person1','name') FROM table

The JSON you have shown is:
A list (as indicated by [])
That contains a dictionary
That contains a dictionary
You will first need to extract the first list element, then use the command you have supplied.
Try something like:
SELECT
json_extract_path(
json_extract_array_element_text(column_name::json, 0),
'person1',
'name'
)
FROM table

Related

psql - Check if json value has specific property

I'm trying to delete rows from a table depending on a specific value on a details column which is of json type.
The column is expected to have a json value like this one:
{
"tax": 0,
"note": "",
"items": [
{
"price": "100",
"quantity": "1",
"description": "Test"
}
]
}
The objects inside items could have a name entry or not. I'd like to delete those that don't have that entry.
NOTE: All objects inside items have the same entries so all of them will have or will not have the name entry
You can use a JSON path expression.
delete from the_table
where details::jsonb ## '$.items[*].name <> ""'
This checks if there is at least one array element where the name is not empty. Note that this wouldn't delete rows with an array element having "name": ""
As you didn't use the recommended jsonb type (which is the one that supports all the nifty JSON path operators), you need to cast the column to jsonb.

Oder of my json request is getting sorted in alphabetical order when i am getting data from data file.i dnt want my json request to get sorted

{
"ID":0,
"OrganizationId":"",
"OrganizationName":"",
"Name":"",
"IsActive":"True",
"Type":2,
"AppliesTo":1,
"TagHOD":"",
"DisplayAsPrimary":"false",
"Values":[
]
}
Above is my json request which I have stored in a data file
Below is my json request body which I am getting after sending a parameter into it. It is sorted into alphabetical order which I don't want. I want the same order as above eg ID Should be first then OrganizationId
{
"AppliesTo": 1,
"DisplayAsPrimary": "false",
"ID": 0,
"IsActive": "True",
"Name": "TAG1205510333275",
"OrganizationId": 2404,
"OrganizationName": "",
"TagHOD": "",
"Type": 2,
"Values": [
{
"HODEmail": "tagsapiautomationae#mailinator.com",
"Id": 1,
"IsDeleted": false,
"Text": "Level20"
}
]
}
The JSON specification states: "An object is an unordered set of name/value pairs."
When working with JSON (and objects in most languages), the properties in objects are inherently unordered. You can't rely on different systems giving you the properties in the same order you supply them. In fact, you can't even rely on a single system giving you the properties in the same order all the time within a given execution of the code, even though many systems do behave that way.
If you want to preserve ordering, you either need to use an array to store the data, or you can use an array of object property names that stores the keys in the order you want, so you can use that array to reference them in the desired order later.
EG:
keyorder = ["ID",
"OrganizationId",
"OrganizationName",
"Name",
"IsActive",
"Type",
"AppliesTo",
"TagHOD",
"DisplayAsPrimary",
"Values"
]
You can then loop over this array when accessing elements in your object, so you are always accessing them in your defined order.
In python, with an object named "data" this would look like:
for key in keyorder:
print data.get(key)

how to prevent the json data output being alphabetically sorted and stored in mysql work?

Hi I'm trying to insert complex json data in mysql workbench but my json data being inserted alphabetically sorted. How do I get json data with same order which I passed in insert query?
Create table:
CREATE TABLE payload ( `id` INT NOT NULL,
`json` JSON NOT NULL,
PRIMARY KEY (`id`));
Insert Json
INSERT INTO payload ( id, json)
VALUES (2, '{
"request": "release",
"type": [
{
"type" : 1
}
],
"start": [
{
"type": "sample",
"id": "01",
"content": [
{
"name": "jon",
"email": "jon#gmail.com"
}
]
}
]
}');
stored json in database after select * table name:
'3', '{\"type\": [{\"type\": 1}], \"start\": [{\"id\": \"01\", \"type\": \"sample\", \"content\": [{\"name\": \"jon\", \"email\": \"jon#gmail.com\"}]}], \"request\": \"release\"}'
Actually I want to have store my json same as my inserted json in database.
Is there a way to prevent the json data being alphabetically sorted?
Thanks.
Mysql will automatically sort the keys of a JSON object before it's stored.
I had the same problem!
The solution is to change the column type to 'text' and then the order of keys will not be changed!
Use serialize before storing. The conversion will make the array unrecognizable to MySQL so when retrieved and restored with unserialize it will be in the exact same order as before storage.
The drawback is the native MySQL json functions and methods can't be used to search and manipulate the array. Serializing is good only for storing and retrieving.
The only other way is to add a key with a value representing the array's sort order. That drawback is that the array must be sorted to restore it to its original state.

Select Objects from Array of Objects that match a property in MYSQL JSON

I have a table with 1 JSON type column city in a MySQL database that stores a JSON array of city objects with following structure:
{
"cities": [
{
"id": 1,
"name": "Mumbai",
"countryID": "9"
},
{
"id": 2,
"name": "New Delhi",
"countryID": "9"
},
{
"id": 3,
"name": "Abu Dhabi",
"countryID": "18"
}
]
}
I want to select objects from the cities array having countryID = 90 but I am stuck as the array of objects is stored in a single column city which is preventing me from doing a (*) with WHERE JSON_CONTAINS(city->'$.cities', JSON_OBEJECT('countryID', '90')).
My query looks like this and I am not getting anywhere,
SELECT JSON_EXTRACT(city, '$.cities') FROM MyTable WHERE JSON_CONTAINS(city->'$.cities', JSON_OBJECT('countryID', '90'))
It'd be a great help if someone can point me in right direction or gimme a solution to this.
Thanks
If you are using MySQL 8.0, there is a feature called JSON table functions. It converts JSON data into tabular form.Then onward you can filter the result.
The query to acheive the same is given below
Select country
FROM json_cal,
JSON_TABLE(
city,
"$.cities[*]" COLUMNS(
country JSON PATH "$",
NESTED PATH '$.countryID' COLUMNS (countryID TEXT PATH '$')
)
) AS jt1
where countryID = 90;
The DB Fiddle can be found here
More information on JSON Table functions can be found here

How to replace JSON key's value in mysql

I have a mysql JSON column like:
column value
data [{ "report1": { "result": "5"}, "report2": {"result": "6"}, "report3": {"a": "4"}}, {"report1": { "result": "9"},"report4": {"details": "<b>We need to show the details here</b>"}, "report3": {"result": "5"}}]
another instance of data is:
[{ "report1": { "result": "5"}, "report2": {"result": "6"}, "report3": {"a": "4"}}, {"report1": { "result": "9"}, "report3": {"result": "5"},"report4": {"details": "<b>We need to show the details here</b>"}}]
In above record the key is present on 2nd index.
And in this:
[{ "report1": { "result": "5"}, "report2": {"result": "6"}, "report3": {"a": "4"}}, {"report1": { "result": "9"}, "report3": {"result": "5"}}]
The key is not present.
I need to replace {"details": "<b>We need to show the details here</b>"}, i.e. key report4's value with just [], I need now data in this report.
Actually, the logic for generating data have been changed from XML data to JSON for only that key, so, we need to replace it with a blank array, the target type now, without affecting the other data.
Is there any direct solution to that? I'm avoiding creating procedures here.
So, The Target data will be:
[{ "report1": { "result": "5"}, "report2": {"result": "6"}, "report3": {"a": "4"}}, {"report1": { "result": "9"},"report4": [], "report3": {"result": "5"}}]
And yes the keys in JSON are not consistent, means, a key may present in next or previous record in the table but may not present in this record.
The column should be of type JSON to use MySQL's JSON features efficiently. Then use the JSON modification functions, such as JSON_REPLACE.
Since each value contains a JSON array whose size may not be known in advance, you can create a small utility function to modify each element in the array.
create function modify_json(val json)
returns json
deterministic
begin
declare len int default json_length(val);
declare i int default 0;
while i < len do
# Replace the report4 property of the i'th element with an empty list
set val = json_replace(val, concat('$[', i, '].report4'), '[]');
set i = i + 1;
end while;
return val;
end;
With your utility function, update the records:
update table set data = modify_json(data)
where json_contains_path(data, 'one', '$[*].report4');
The records containing at least one element with a report4 property will be updated according to the modify_json function in this case. You could achieve the same thing with multiple update commands that operate on each index of the JSON array separately.
If the column can't be of type JSON for some reason, then you can allow MySQL to coerce the data or your program can marshall the string into a JSON object, modify the data, then serialize it to a string, and update the row.