Apex · Oracle · REST

Enviar grandes bloques de datos usando JSON y POST – Oracle APEX RESTful Services

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

img_1

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í:

img_2

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.

img_3

Leave a comment