21 JSON用のPL/SQLオブジェクト型の使用

JSON用のPL/SQLオブジェクト型を使用した例についていくつか説明します。

関連項目:

例21-1 インメモリーJSONオブジェクトの構成およびシリアライズ

この例では、関数parseを使用して、nameという1つのフィールドを持つJSONオブジェクトを表すJSONデータの文字列を解析し、オブジェクト型JSON_ELEMENT_Tのインスタンスjeを作成します。このインスタンスは、オブジェクトを表すかどうかを確認するために、イントロスペクション・メソッド(述語)is_object()を使用してテストされます。

インスタンスがオブジェクトを表す場合(述語がjeに対してTRUEを戻す)、JSON_OBJECT_Tのインスタンスにキャストされて変数joに割り当てられます。次に、オブジェクト型JSON_OBJECT_Tのメソッドput()を使用して、オブジェクト・フィールドpriceが値149.99で追加されます。

最後に、JSON_ELEMENT_Tインスタンスのje (JSON_OBJECT_Tインスタンスのjoと同じインメモリーデータ)は、メソッドto_string()を使用して文字列にシリアライズされ、この文字列がプロシージャDBMS_OUTPUT.put_lineを使用して出力されます。結果の出力には、更新されたオブジェクトが{"name":"Radio-controlled plane","price":149.99}として表されます。

更新された一時オブジェクトjeは、ここで出力のためだけにシリアライズされますが、結果のテキストはデータベースには格納されません。場合によっては、サンプル・コードが実行された後に、オブジェクト型インスタンスjeおよびjoに割り当てられているメモリーは、ガベージ・コレクションによって回収されます。

DECLARE
  je JSON_ELEMENT_T;
  jo JSON_OBJECT_T;
BEGIN
  je := JSON_ELEMENT_T.parse('{"name":"Radio controlled plane"}');
  IF (je.is_Object) THEN
    jo := treat(je AS JSON_OBJECT_T);
    jo.put('price', 149.99);
  END IF;
  DBMS_OUTPUT.put_line(je.to_string);
END;
/

例21-2 メソッドGET_KEYS()を使用したオブジェクト・フィールドのリストの取得

PL/SQLメソッドget_keys()が、PL/SQLオブジェクト型JSON_OBJECT_Tに対して定義されています。これにより、PL/SQLオブジェクト型JSON_KEY_LISTのインスタンスが返されます。これは、VARCHAR2(4000)のVARRAYです。VARRAYには指定されたJSON_OBJECT_Tインスタンスのフィールド名すべてが格納されています。

この例は、get_keys()によって戻されるフィールドにわたって繰り返し処理し、これらのフィールドをPL/SQLオブジェクト型JSON_ARRAY_Tのインスタンスに追加します。次に、メソッドto_string()を使用して、そのJSON配列をシリアライズして結果の文字列を出力します。

DECLARE
  jo          JSON_OBJECT_T;
  ja          JSON_ARRAY_T;
  keys        JSON_KEY_LIST;
  keys_string VARCHAR2(100);
BEGIN
  ja := new JSON_ARRAY_T;
  jo := JSON_OBJECT_T.parse('{"name":"Beda", 
                              "jobTitle":"codmonki", 
                              "projects":["json", "xml"]}');
  keys := jo.get_keys;
  FOR i IN 1..keys.COUNT LOOP
     ja.append(keys(i));
  END LOOP;
  keys_string := ja.to_string;
  DBMS_OUTPUT.put_line(keys_string);
END;
/

出力は、["name","jobTitle","projects"]のようになります。

例21-3 メソッドPUT()を使用したJSON文書の部分的な更新

この例では、表j_purchaseorderのJSON列po_documentに含まれる発注書の文書をそれぞれ更新します。各文書内のJSON配列LineItemsにわたって繰り返し処理し(変数li_arr)、明細項目オブジェクトごとに合計金額と数量を計算し(変数li_obj)、メソッドput()を使用してこれらの合計を新しいフィールドtotalQuantityおよびtotalPriceの値としてli_objに追加します。これは、ユーザー定義の関数add_totalsを使用して行われます。

ここでのSELECT文では、更新された文書の1つが選択されます。

CREATE OR REPLACE FUNCTION add_totals(purchaseOrder IN VARCHAR2) RETURN VARCHAR2 IS
  po_obj        JSON_OBJECT_T;
  li_arr        JSON_ARRAY_T;
  li_item       JSON_ELEMENT_T;
  li_obj        JSON_OBJECT_T;
  unitPrice     NUMBER;
  quantity      NUMBER;
  totalPrice    NUMBER := 0;
  totalQuantity NUMBER := 0;
BEGIN
  po_obj := JSON_OBJECT_T.parse(purchaseOrder);
  li_arr := po_obj.get_Array('LineItems');
  FOR i IN 0 .. li_arr.get_size - 1 LOOP
    li_obj := JSON_OBJECT_T(li_arr.get(i));
    quantity := li_obj.get_Number('Quantity');
    unitPrice := li_obj.get_Object('Part').get_Number('UnitPrice');
    totalPrice := totalPrice + (quantity * unitPrice);
    totalQuantity := totalQuantity + quantity;
  END LOOP;
  po_obj.put('totalQuantity', totalQuantity);
  po_obj.put('totalPrice', totalPrice);
  RETURN po_obj.to_string;
END;
/

UPDATE j_purchaseorder SET (po_document) = add_totals(po_document);

SELECT po_document FROM j_purchaseorder po WHERE po.po_document.PONumber = 1600;

この更新された文書が選択されます。

{"PONumber": 1600,
 "Reference": "ABULL-20140421",
 "Requestor": "Alexis Bull",
 "User": "ABULL",
 "CostCenter": "A50",
 "ShippingInstructions": {"name": "Alexis Bull",
                          "Address": {"street": "200 Sporting Green",
                                      "city": "South San Francisco",
                                      "state": "CA",
                                      "zipCode": 99236,
                                      "country": "United States of America"},
                          "Phone": [{"type": "Office", "number": "909-555-7307"},
                                    {"type": "Mobile", "number": "415-555-1234"}]},
 "Special Instructions": null,
 "AllowPartialShipment": true,
 "LineItems": [{"ItemNumber": 1,
                "Part": {"Description": "One Magic Christmas",
                         "UnitPrice": 19.95,
                         "UPCCode": 13131092899},
                "Quantity": 9.0},
               {"ItemNumber": 2,
                "Part": {"Description": "Lethal Weapon",
                         "UnitPrice": 19.95,
                         "UPCCode": 85391628927},
                "Quantity": 5.0}],
 "totalQuantity": 14,
 "totalPrice": 279.3}