How to convert a PL SQL collection into json_object? - json

I have a type named codelist if table of varchar. a variable called "final" of type codelist needs to be converted as json_object.
Like this New = ('1','2','3') needs to be converted to json format like below
{
"New" : ['1','2','3']
}
Please help

try this
declare
tag1 json_object_t;
tag2 json_object_t;
array json_array_t;
begin
tag1:= json_object_t();
tag1.put('Date', sysdate);
tag1.put('Your header', "hellow");
tag2:= json_object_t();
tag2.put('pos1', test(1).1);
tag2.put('pos2', teste(2).2);
array.append(tag2);
end;
If I wasn't very clear, you can follow this link - https://dzone.com/articles/relational-to-json-with-plsql

Related

TJSON.JsonToObject<classname> not working in Delphi

I am trying to convert Json trying to class object, but the values are not appearing in the new object variable. The resulting object has blank value in string and 0 in integer.
Thanks in advance.
Code:
type
Student =class
public
Name : string;
Age : Integer;
end;
procedure TForm2.Button5Click(Sender: TObject);
var
Student1, Student2: Student;
STR: string;
begin
Student1 := Student.Create;
Student2 := Student.Create;
try
Student1.Name := 'Sam';
Student1.Age := 24;
str := TJson.ObjectToJsonString(Student1);
Form2.outputMemo.Lines.Add(str);
Student2 := TJSON.JsonToObject<Student>(str);
Form2.outputMemo.Lines.Add(Student2.Name);
Form2.outputMemo.Lines.Add(Student2.Age.ToString);
finally
Student1.Free;
Student2.Free;
end;
//Form2.outputMemo.Lines.Text :=TJson.ObjectToJsonObject(Student1);
end;
Output:
{"name":"Sam","age":24}
0
Edit:
I just saw this, and it worked when I changed the names to FName and FAge... what a sorcery!, can anyone please explain the logic behind this?
Delphi Rest.JSON JsonToObject only works with f variables
The internal mapping of JSON fields to Delphi fields is prefixing them with F and changing the following character to upper case. If you want complete control over this you can specify the JSON name with an attribute:
type
Student =class
public
[JSONName('name')]
Name : string;
[JSONName('age')]
Age : Integer;
end;
Note that the JSON names given are case sensitive.
You need to include REST.Json.Types to the uses so that the attribute declaration can be found.

Removing attributes from oracle json object

Use case:
Application requires a subset of attributes, based on business rules
Example:
Some students do not require to enter in home address
Database : Oracle
Proposed implementation:
Build json object containing all possible attribute named pairs, then selectively remove specific named pairs
Issue:
Hoped to use native oracle function to remove the specified named pair.
e.g json_object.remove_attribute('home_address');
However Oracle do not appear to provide any such method.
Workaround : Convert json_object to VARCHAR2 string, and then use combination of INSTR and REPLACE to remove named pair.
Illustrative code:
DECLARE
CURSOR cur_student_json (p_s_ref IN VARCHAR2) IS
SELECT JSON_OBJECT(
,'s_surname' value s.s_surname
,'s_forename_1' value s.s_forename_1
,'s_home_address_1' value s.s_home_address_1
RETURNING VARCHAR2 ) student_json
FROM students s
WHERE s.s_ref = p_s_ref;
BEGIN
FOR x IN cur_student_json (p_s_ref) LOOP
vs_student_json:=x.student_json;
EXIT;
END LOOP;
-- Determine student type
vs_student_type:=get_student_type(p_s_ref);
-- Collect list of elements not required, based on student type
FOR x IN cur_json_inorout(vs_student_type) LOOP
-- Remove element from the json
vs_student_json:=json_remove(vs_student_json,x.attribute);
END LOOP;
END;
/
Question:
There must be an elegant method to achieve requirement
Classify under RTFM. Needs Oracle 12.2
DECLARE
-- Declare an object of type JSON_OBJECT_T
l_obj JSON_OBJECT_T;
-- Declare cursor to build json object
CURSOR cur_student_json (p_s_ref IN VARCHAR2) IS
SELECT JSON_OBJECT(
,'s_surname' value s.s_surname
,'s_forename_1' value s.s_forename_1
,'s_home_address_1' value s.s_home_address_1
) student_json
FROM students s
WHERE s.s_ref = p_s_ref;
BEGIN
-- Initialise object
l_obj := JSON_OBJECT_T();
-- Populate the object
FOR x IN cur_student_json (p_s_ref) LOOP
l_obj:=JSON_OBJECT_T.parse(x.student_json);
EXIT;
END LOOP;
-- Determine student type
vs_student_type:=get_student_type(p_s_ref);
-- Collect list of elements not required, based on student type
FOR x IN cur_json_inorout(vs_student_type) LOOP
-- Remove element from the json
l_obj.remove(x.attribute);
END LOOP;
-- Display modified object
dbms_output.put_line(l_obj.stringify);
END;
/

Passing json containing array of objects to PostgreSQL function throws malformed array literal. Unexpected array element

I have a simple PostgreSQL function I want to pass complex JSON to:
CREATE OR REPLACE FUNCTION foo(sync_data json)
RETURNS json AS
$body$
DECLARE
...
END;
$body$ LANGUAGE plpgsql;
Calling it with something like this:
SELECT foo('{"deviceId": 1, "shops": [{"id": 1}, {"id": 2}]}'::json);
gives me the following error:
ERROR: malformed array literal: "{"id": 1}"
DETAIL: Unexpected array element.
CONTEXT: PL/pgSQL function foo(json) line 8 at SQL statement
SQL state: 22P02
I need to pass complex JSON as a parameter, containing arrays of objects.
Thanks!
PS: Here is the full function text:
CREATE OR REPLACE FUNCTION foo(sync_data json)
RETURNS json AS
$body$
DECLARE
res_json json;
device_id integer;
shops json ARRAY;
BEGIN
SELECT json_extract_path(sync_data, 'deviceId') INTO device_id;
SELECT json_array_elements(json_extract_path(sync_data, 'shops')) INTO shops;
SELECT json_build_object('devId', device_id) INTO res_json;
RETURN res_json;
END;
$body$ LANGUAGE plpgsql;
The problem was with the syntax inside the function.
The correct syntax for parsing array of objects and assigning it to json ARRAY:
CREATE OR REPLACE FUNCTION foo(sync_data json)
RETURNS json AS
$body$
DECLARE
res_json json;
device_id integer;
shops json ARRAY;
BEGIN
SELECT json_extract_path(sync_data, 'deviceId') INTO device_id;
shops := ARRAY(SELECT json_array_elements(sync_data->'shops'));
SELECT json_build_object('Dev_id', device_id, 'shop1', shops[1], 'shop2', shops[2]) INTO res_json;
RETURN res_json;
END;
$body$ LANGUAGE plpgsql;
Thanks to eurotrash and Abelisto!

How to prevent 'invalid input syntax for type json' in Postgres, when records contain a mix of json or strings

I have a text column that contains JSON and also plan text. I want to convert it to JSON, and then select a particular property. For example:
user_data
_________
{"user": {"name": "jim"}}
{"user": {"name": "sally"}}
some random data string
I've tried:
select user_data::json#>'{user,name}' from users
I get:
ERROR: invalid input syntax for type json
DETAIL: Token "some" is invalid.
CONTEXT: JSON user_data, line 1: some...
Is it possible to prevent this?
If you want to skip the rows with invalid JSON, you must first test if the text is valid JSON. You can do this by creating a function which will attempt to parse the value, and catch the exception for invalid JSON values.
CREATE OR REPLACE FUNCTION is_json(input_text varchar) RETURNS boolean AS $$
DECLARE
maybe_json json;
BEGIN
BEGIN
maybe_json := input_text;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
RETURN TRUE;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
When you have that, you could use the is_json function in a CASE or WHERE clause to narrow down the valid values.
-- this can eliminate invalid values
SELECT user_data::json #> '{user,name}'
FROM users WHERE is_json(user_data);
-- or this if you want to fill will NULLs
SELECT
CASE
WHEN is_json(user_data)
THEN user_data::json #> '{user,name}'
ELSE
NULL
END
FROM users;
Use this function:
create or replace function is_json(text)
returns boolean language plpgsql immutable as $$
begin
perform $1::json;
return true;
exception
when invalid_text_representation then
return false;
end $$;
Test:
with users(user_data) as (
values
('{"user": {"name": "jim"}}'),
('not json'),
('{"user": {"name": "sally"}}'),
('also not json')
)
select user_data::json#>'{user,name}' as name
from users
where is_json(user_data);
name
---------
"jim"
"sally"
(2 rows)
Others have already suggested ways to check if the JSON is valid, but I feel that rather than check that, why not already cast it?
I use this function (JSONB, but you can easily change it to JSON):
CREATE OR REPLACE FUNCTION safe_cast_to_jsonb(input TEXT) RETURNS JSONB AS
$$
DECLARE
output JSONB DEFAULT NULL;
BEGIN
BEGIN
output := input::JSONB;
EXCEPTION
WHEN OTHERS THEN RAISE NOTICE 'INVALID JSONB';
RETURN NULL;
END;
RETURN output;
END;
$$ LANGUAGE plpgsql;

how to convert json to composite type

i'm trying once again to work with postgres 9.4 and the new json functionalities and might have encountered a bug. The Problem is that once i have generated a json-string via to_json(..) i cant transform it back to an Composite type because postgres cant handle the json-array inside.
When i write it in postgres Notation it works and i can even access all the fields inside the Array.
Does anyone knows a better workarround?
Example 1: composite type to json and back
DROP TYPE IF EXISTS myType;
CREATE TYPE myType AS (
since TIMESTAMP,
words TEXT[]
);
DO $$
DECLARE
_my_variable myType;
_my_json JSON;
BEGIN
_my_variable := ROW(now(),ARRAY['Here','is','a','List','of','Words']);
_my_json := to_json(_my_variable);
RAISE INFO 'how my json looks like: %', _my_json;
--{"since":"2015-06-30T09:12:35.12346","word":["Here","is","a","List","of","Words"]}
_my_variable := json_populate_record(NULL::myType,_my_json);
--ERROR: malformed array literal: "["Here","is","a","List","of","Words"]"
--DETAIL: "[" must introduce explicitly-specified array dimensions.
--CONTEXT: PL/pgSQL function inline_code_block line 13 at assignment
END $$;
Example 2: json with postgres-notation like array to composite type
DO $$
DECLARE
_my_variable myType;
_my_json JSON;
BEGIN
_my_json := '{"since":"2015-06-30T09:12:35.12346","words": "{Here,is,a,List,of,Words}" }';
_my_variable := json_populate_record(NULL::myType,_my_json);
RAISE INFO 'how my object looks like: %', _my_variable;
RAISE INFO 'how my array looks like: %', _my_variable.words;
--("2015-06-30 09:12:35.12346","{Here,is,a,List,of,Words}")
END $$;