PL/SQL with JSON (list of object) parsing - json

Since I am writing, there is something that I am not able to understand. I have the following JSON object data that is indented. I would like to retrieve the values that are associated with “industry” and “exchange” for each “response” in PL/SQL in Oracle 12. I have installed the JSON package found in the forum https://github.com/pljson/pljson. All solution that I have found were not indented, so I am not sure if this is the reason, for not being able to access the information. Any suggestion or article that could help me would be greatly appreciated.
Thanks in advance.
This is my JSON string
{
"response":{
"MSFT":{
"meta":{
"status":"ok"
},
"results":{
"industry":{
"data":"Software - Infrastructure",
"meta":{
"status":"ok"
}
},
"exchange":{
"data":"NASDAQ",
"meta":{
"status":"ok"
}
}
}
},
"AAPL":{
"meta":{
"status":"ok"
},
"results":{
"industry":{
"data":"Consumer Electronics",
"meta":{
"status":"ok"
}
},
"exchange":{
"data":"NASDAQ",
"meta":{
"status":"ok"
}
}
}
}
},
"meta":{
"status":"ok",
"url":"http://testdata.com/api/v3/companies/AAPL,MSFT/info/exchange,industry"
}
}
This is a modified sample code that I have found on the forum base on this link
Parse JSON into Oracle table using PL/SQL
create or replace procedure json4(w_periode in varchar2) is
begin
DECLARE
l_param_list VARCHAR2(512);
l_http_request UTL_HTTP.req;
l_http_response UTL_HTTP.resp;
l_response_text VARCHAR2(32767);
l_list json_list;
obj json := json();
arr json_list := json_list();
BEGIN
-- service's input parameters
-- ...set input parameters
-- UTL_HTTP.write_text(l_http_request, l_param_list);
l_response_text := '{"response": {"MSFT": {"meta": {"status": "ok"}, "results": {"industry": {"data": "Software - Infrastructure", "meta": {"status": "ok"}}, "exchange": {"data": "NASDAQ", "meta": {"status": "ok"}}}}, "AAPL": {"meta": {"status": "ok"}, "results": {"industry": {"data": "Consumer Electronics", "meta": {"status": "ok"}}, "exchange": {"data": "NASDAQ", "meta": {"status": "ok"}}}}}, "meta": {"status": "ok", "url": "http://testurl.com"}}';
/* -- get Response and obtain received value
l_http_response := UTL_HTTP.get_response(l_http_request);*/
/* UTL_HTTP.read_text(l_http_response, l_response_text);
*/
obj := json(l_response_text);
DBMS_OUTPUT.put_line(l_response_text);
/* l_list := json_list(l_response_text);*/
/*arr := json_list(obj.get('industry'));*/
end;
end json4;

I found a solution. The link in the post need's to be bracket as an array. In my varchar2 I had to insert the "[" symbol at beginning and at the end. The problem is that it will only parse the JSON if it is not indented, from my understanding.
I then install the APEX5 package, it was able to handle indented code. I follow the installation procedure https://www.youtube.com/watch?v=JGnkPVq7V98 and on the first try it work perfectly.
Hope this help

Related

Generating JSON with multiple functions using Oracle APEX_JSON

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;
/

How to parse this type of JSON data in Delphi?

How do I parse the following Json in Delphi?
This is my first post, and I've taken care to search as much as I can before asking this question,
so please kindly let me know if I posted wrongly in any way.
I would like to get the value of "name_of_centre" in the "records" array
Thank you for any kind assistance.
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
jsonRoot: TJSONValue;
jsonObj: TJSONObject;
jsonArr: TJSONArray;
begin
jsonRoot := TJSONObject.ParseJSONValue(memo2.Lines.text);
try
jsonObj := jsonRoot as TJSONObject;
jsonObj := jsonObj.GetValue('result') as TJSONObject;
jsonArr := jsonObj.GetValue('records') as TJSONArray;
showmessage( jsonArr.Count.ToString ); // works ok
for i := 0 to jsonArr.Count - 1 do
begin
jsonObj := jsonArr.Items[i] as TJSONObject;
showmessage( jsonObj.GetValue('name_of_centre').Value ); // error here
end;
finally
jsonRoot.Free;
end;
end;
I've checked out
Delphi parsing a Json with multiple array types?
How to parse this json data in Delphi 10 Seattle?
(especially this one)
and a few other links... but the JSON format seems different.
Any advice?
{
"help": "testing",
"success": true,
"result": {
"resource_id": "data_resource",
"fields": [
{
"type": "int4",
"id": "_id"
},
{
"type": "text",
"id": "name_of_centre"
},
{
"type": "text",
"id": "location_of_centre"
},
{
"type": "text",
"id": "type_of_centre"
},
{
"type": "text",
"id": "owner"
},
{
"type": "numeric",
"id": "no_of_outlets"
},
{
"type": "numeric",
"id": "no_of_branches"
}
],
"records": [
{
"location_of_centre": "Kings Road",
"no_of_outlets": "12",
"no_of_branches": "0",
"name_of_centre": "Kings Road Centre",
"type_of_centre": "HC",
"owner": "Private",
"_id": 1
},
{
"location_of_centre": "Queens",
"no_of_outlets": "14",
"no_of_branches": "1",
"name_of_centre": "Queens Centre",
"type_of_centre": "HC",
"owner": "Public",
"_id": 2
}
],
"_links": {
"start": "ignore",
"next": "ignore2"
},
"limit": 2,
"total": 10
}
}
Thanks for the many replies.
Olivier : I've included the error in this amended code.
Peter : I tried using
jsonRoot.GetValue('result.records[0].name_of_centre')
and it does give me the value of name_of_centre. Good start.
But I'm hoping to get this code to give me the number of items in Array and I iterate the array, instead of hard-code. Thanks.
Remy : strangely though, it works today. It doesn't get Invalid Typecast
at showmessage( jsonObj.GetValue('name_of_centre').Value );
fpiette : I use Delphi 10.3 RIO.
Thanks to everyone for replying.
Is there a need to use jsonRoot.Free; -- i saw this in a posting on stackoverflow.com... How about jsonObj.Free?
jsonRoot := TJSONObject.ParseJSONValue(memo2.Lines.text);
try
jsonObj := jsonRoot as TJSONObject;
jsonObj := jsonObj.GetValue('result') as TJSONObject;
showmessage( jsonObj.ToString );
jsonArr := jsonObj.GetValue('records') as TJSONArray;
showmessage( jsonArr.Count.ToString );
for i := 0 to jsonArr.Count - 1 do
begin
jsonObj := jsonArr.Items[i] as TJSONObject;
if jsonObj .GetValue('name_of_centre').Value = null then
showmessage('null');
// previously had an Invalid Typecast
showmessage( jsonObj.GetValue('name_of_centre').Value );
end;
finally
jsonRoot.Free;
end;

select values in json into other json (Postgres)

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

swift json error dankogai/swift-json

I'm using dankogai/swift-json to get a json response from a web service..
Everything is going fine but, sometimes the web service can't give me back any response, because there is no data in the database. It's not a problem.
But I have to handle when I get "null" from the web service.
This is my json request:
let json = JSON(url:"http://79.172.249.175:7001/RestWebServiceApp/webresources/entity.bkkmainprtable/"+lat+"/"+lon)
// json is valid json object...
if (json["bkkMainPrTable"]["routeShName"].isArray){
for (k, v) in json["bkkMainPrTable"] {
colors.append(v["routeShName"].description + " - " + v["stopName"].description)
}
}
// json is not a valid json object...
else {
colors.append("Nincs elérhető járat")
sendKallerBtn.setTitle("No Post", forState: UIControlState.Normal)
}
But, it is always nil.. and alway step into else..
Can anybody help me how to check is this a valid json object or not..
Thank you!
Solved with this:
if (json["bkkMainPrTable"].asError == nil){
....
}
Sure, I can help.
I've made a call:
http://79.172.249.175:7001/RestWebServiceApp/webresources/entity.bkkmainprtable/47.490477/19.030486
got the response:
{"bkkMainPrTable":[{"id":"7857","routType":"3","routeShName":"178","stopId":"F00002","stopLat":"47.490477","stopLatStirng":"47.490477","stopLon":"19.030486","stopLonString":"19.030486","stopName":"Zsolt utca"},{"id":"7954","routType":"3","routeShName":"105","stopId":"F00087","stopLat":"47.496422","stopLatStirng":"47.496422","stopLon":"19.03071","stopLonString":"19.03071","stopName":"Krisztina tĂŠr"},{"id":"7946","routType":"0","routeShName":"18","stopId":"F00080","stopLat":"47.493779","stopLatStirng":"47.493779","stopLon":"19.038183","stopLonString":"19.038183","stopName":"DĂłzsa GyĂśrgy tĂŠr"},{"id":"7943","routType":"3","routeShName":"916","stopId":"F00077","stopLat":"47.494777","stopLatStirng":"47.494777","stopLon":"19.037665","stopLonString":"19.037665","stopName":"DĂłzsa GyĂśrgy tĂŠr"}]}
put it there:
http://jsonlint.com/
and got the result:
{
"bkkMainPrTable": [
{
"id": "7857",
"routType": "3",
"routeShName": "178",
"stopId": "F00002",
"stopLat": "47.490477",
"stopLatStirng": "47.490477",
"stopLon": "19.030486",
"stopLonString": "19.030486",
"stopName": "Zsolt utca"
},
{
"id": "7954",
"routType": "3",
"routeShName": "105",
"stopId": "F00087",
"stopLat": "47.496422",
"stopLatStirng": "47.496422",
"stopLon": "19.03071",
"stopLonString": "19.03071",
"stopName": "Krisztina tĂŠr"
},
{
"id": "7946",
"routType": "0",
"routeShName": "18",
"stopId": "F00080",
"stopLat": "47.493779",
"stopLatStirng": "47.493779",
"stopLon": "19.038183",
"stopLonString": "19.038183",
"stopName": "DĂłzsa GyĂśrgy tĂŠr"
},
{
"id": "7943",
"routType": "3",
"routeShName": "916",
"stopId": "F00077",
"stopLat": "47.494777",
"stopLatStirng": "47.494777",
"stopLon": "19.037665",
"stopLonString": "19.037665",
"stopName": "DĂłzsa GyĂśrgy tĂŠr"
}
]
}
Valid JSON

Generate a sample JSON with an array in it in Delphi XE5

coming from .NET, I've been unable to do what I consider a simple task.
I want to use TJSONObject, TJSONArray, TJSONPair etc to construct a simple JSON like the following:
{
"APIKEY": "sadfsafsafdsa",
"UserID": "123123123",
"Transactions:"
[{
"TransactionID": 1,
"Amount": 23
},
{
"TransactionID": 2,
"Amount": 53
}]
}
Logically what I would do is create a TJSONObject and then add 3 TJSONPair, the third pair being TJSONPair of Transactions and a TJSONArrary
However, I am not getting what I wanted. For the Transactions pair, if I convert my transactions TJSONArrary to string, then it comes out as a long string which is invalid.
Any help would be appreciated.
Try this
{$APPTYPE CONSOLE}
{$R *.res}
uses
Data.DBXJSON,
System.SysUtils;
var
LJson, LJsonObject: TJSONObject;
LArr: TJSONArray;
begin
try
ReportMemoryLeaksOnShutdown:=True;
LJsonObject := TJSONObject.Create;
try
LJsonObject.AddPair(TJSONPair.Create('APIKEY', 'sadfsafsafdsa'));
LJsonObject.AddPair(TJSONPair.Create('UserID', '123123123'));
LArr := TJSONArray.Create;
LJson := TJSONObject.Create;
LJson.AddPair(TJSONPair.Create('TransactionID', '1'));
LJson.AddPair(TJSONPair.Create('Amount', '23'));
LArr.Add(LJson);
LJson := TJSONObject.Create;
LJson.AddPair(TJSONPair.Create('TransactionID', '2'));
LJson.AddPair(TJSONPair.Create('Amount', '53'));
LArr.Add(LJson);
LJsonObject.AddPair(TJSONPair.Create('Transactions', LArr));
Write(LJsonObject.ToString);
finally
LJsonObject.Free; //free all the child objects.
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
This will create a JSON like so
{ "APIKEY": "sadfsafsafdsa",
"UserID": "123123123",
"Transactions":
[{
"TransactionID": "1",
"Amount": "23"
},
{
"TransactionID": "2",
"Amount": "53"
}]
}