Esto podría ser una tarea sencilla si ya vimos en otro blog como usar un REST con uno o dos parámetros, pero que pasa si necesitamos enviar muchas propiedades y nodos dentro de un objeto JSON.
Este será nuestro ejemplo que enviaremos.
{
"data_json": [
{
"deptno": 10,
"dname": "ACCOUNTING",
"loc": "NEW YORK",
"employees": [
{
"empno": 7839,
"ename": "KING",
"job": "PRESIDENT",
"sal": 50000,
"deptno": 10
},
{
"empno": 7782,
"ename": "CLARK",
"job": "MANAGER",
"sal": 2450,
"deptno": 10
}
]
},
{
"deptno": 20,
"dname": "RESEARCH",
"loc": "DALLAS",
"employees": [
{
"empno": 7566,
"ename": "JONES",
"job": "MANAGER",
"sal": 2975,
"deptno": 20
}
]
}
]
}
Creamos nuestro servicio RESTful del tipo POST
El código que agregaremos será:
Recordemos que todo el JSON que enviemos estará dentro de la variable :body
entonces como vimos en otros blogs, manejaremos esta variable como JSON y la convertiremos de acuerdo a nuestras necesidades.
Podemos usar para ello apex_json
o json_table
aquí tengo una demo.
Pueden usar este código como debug para su manejo del JSON.
Nota que la siguiente forma no es la mejor, ya que sería más eficiente hacer el insert en bloque, lo hice de esta forma con fines demostrativos.
Nota2: Si tiene algún inconveniente con el siguiente código, aquí está el en archivo.
declare
l_json_clob clob;
l_json apex_json.t_values;
l_cantidad_depts number;
l_cantidad_empleados number;
l_dept_row dept%rowtype;
l_emp_row emp%rowtype;
begin
-- primero convertimos el BLOB del body a clob
-- entendiendo que lo que se enviara será un JSON
-- solo borramos con fines prácticos para no tener error de constraints.
delete from emp;
delete from dept;
-- tomamos los valores de la llamada JSON
l_json_clob := apex_util.blob_to_clob(p_blob => :body );
apex_json.parse(l_json, l_json_clob);
l_cantidad_depts := apex_json.get_count (p_path => 'data_json' , p_values=> l_json);
l_dept_row := null;
l_emp_row := null;
for i in 1 .. l_cantidad_depts
loop
l_dept_row.deptno := apex_json.get_varchar2 (p_path => 'data_json[%d].deptno', p0 => i, p_values => l_json);
l_dept_row.dname := apex_json.get_varchar2 (p_path => 'data_json[%d].dname', p0 => i, p_values => l_json);
l_dept_row.loc := apex_json.get_varchar2 (p_path => 'data_json[%d].loc', p0 => i, p_values => l_json);
insert into dept (
deptno
, dname
, loc
)
values (
l_dept_row.deptno
, l_dept_row.dname
, l_dept_row.loc
);
apex_json.open_object;
apex_json.write('message', 'Departamento ' || l_dept_row.dname || ' insertado ');
--apex_json.close_object;
-- ahora insertamos los empleados relacionados al DEPT enviado
-- NOTA: de esta forma al hacer el insert independiente por cada departamento podriamos obtener el ID del padre e insertarlo a los hijos.
l_cantidad_empleados := apex_json.get_count (p_path => 'data_json[%d].employees' , p0 => i, p_values=> l_json);
dbms_output.put_line ('.. l_cantidad_empleados: ' || l_cantidad_empleados );
for emp in 1 .. l_cantidad_empleados
loop
l_emp_row.empno := apex_json.get_varchar2 (p_path => 'data_json[%d].employees[%d].empno', p0 => i, p1 => emp, p_values => l_json);
l_emp_row.ename := apex_json.get_varchar2 (p_path => 'data_json[%d].employees[%d].ename', p0 => i, p1 => emp, p_values => l_json);
l_emp_row.job := apex_json.get_varchar2 (p_path => 'data_json[%d].employees[%d].job', p0 => i, p1 => emp, p_values => l_json);
l_emp_row.sal := apex_json.get_varchar2 (p_path => 'data_json[%d].employees[%d].sal', p0 => i, p1 => emp, p_values => l_json);
l_emp_row.deptno := l_dept_row.deptno;
insert into emp (
empno
, ename
, job
, sal
, deptno
)
values (
l_emp_row.empno
, l_emp_row.ename
, l_emp_row.job
, l_emp_row.sal
, l_emp_row.deptno
);
--apex_json.open_object;
apex_json.write('message', 'Empleado ' || l_emp_row.ename || ' insertado ');
--apex_json.close_object;
end loop;
apex_json.close_object;
end loop;
apex_json.open_object;
apex_json.write('success',true);
apex_json.write('message', 'Tareas completadas');
apex_json.close_object;
exception
when others then
apex_json.open_object;
apex_json.write('success',false);
apex_json.write('message', sqlerrm);
apex_json.close_object;
end;
Deberia quedar así:
Finalmente solo necesitamos hacer la prueba, usaremos Postman para ello.
No necesitamos enviar parámetros, solo configurar el body, como tipo raw y enviar el JSON.