23 OCIでのJSONのサポート
SQL型JSONのサポートは、JSONデータ用に設計されています。Oracle DatabaseではJSONデータにJSON型を使用することをお薦めします。
この章には次のトピックが含まれます:
23.1 JSONデータ型のサポート
Oracle Databaseリリース21c以降では、SQL型JSONのサポートは、特にJSONデータ用に設計されています。Oracle DatabaseではJSONデータにJSON型を使用することをお薦めします。これにはバイナリ形式OSONが使用されます。これは、Oracle DatabaseサーバーとOracle Databaseクライアントの両方で問合せおよび更新を迅速に行うための、Oracle用に最適化されたバイナリJSON形式です。JSONデータ型を使用するには、compatible
データベース初期化パラメータに20以上を設定する必要があります。
JSONデータがSQLデータ型JSONの場合、Oracleでは標準のJSON言語のスカラー型(数値、文字列、ブール、nullなど)のセットが拡張され、SQLスカラー型に対応するスカラーが含まれています(binary、date、timestamp、year-month interval、day-second interval、double、floatなど)。これにより、JSON言語が拡張され、JSON言語とSQLの間でスカラー・データの変換がより簡単になり、データの損失がなくなります。
23.1.1 JSONのOCI表現
この項では、JSONのOCI表現について説明します。
標準JSONは、言語または表記法として、オブジェクト、配列、数値、文字列、ブール、nullなどのデータ型が事前定義されています。オブジェクトと配列を除くすべてのJSON言語型はスカラー型です。
OCIJson
記述子は、OCIのJSONドキュメントを表すために使用されます。これは記述子タイプOCI_DTYPE_JSON
で識別されます。この記述子は、OCIDescriptorAlloc()
関数およびOCIDescriptorFree ()
関数を使用して割当ておよび解放できます。ユーザーは、OCIArrayDescriptorAlloc()
関数およびOCIArrayDescriptorFree()
関数をそれぞれ使用して、記述子の配列の割当ておよび解放を行うことができます。
OCIJsonDomDocGet()
関数を使用すると、JsonDomDoc *
で表される基礎となるJSON DOM (Document Object Model)コンテナへの参照を取得できます。JSON DOMドキュメントには、オブジェクト型、配列型またはスカラー型のいずれかのノードが含まれています。
表23-1 型の作成および定数
プログラム変数 | 型定数 |
---|---|
JsonDomScalar |
JZNDOM_SCALAR |
JsonDomArray |
JZNDOM_ARRAY |
JsonDomObject |
JZNDOM_OBJECT |
ノート:
JsonDomNode
は不完全な型です。前述の表に示されている型の値は、(JsonDomNode *)
型に設定できます。
23.2 リリース21cより前のクライアント・ライブラリと互換性
この項では、Oracle Databaseリリース21cより前のクライアント・バージョンをJSONデータ型の問合せに互換性を持たせる方法について説明します。
Oracle Databaseリリース21c以降、JSONデータ型はRDBMSサーバーの21cバージョンとクライアント・ライブラリの21cバージョンの両方でサポートされます。このサポートにより、クライアント・プログラムはJSONデータを問い合せ、ネイティブにデコードできるOSONバイトを受信できます。パフォーマンス向上のためにこの方法をお薦めします。
インスタント・クライアント・バージョンを21cに更新しない場合でも、アプリケーションはJSON型の列のデータを文字列として引き続き読み書きできます。したがって、C OCIプログラムでデータを問い合せるには、SQLT_CHR
、SQLT_BLOB
または SQLT_CLOB
データ型を使用して定義できます。JSONデータがBLOBデータとして抽出される場合、古いクライアントと新しいクライアントの両方について、JSONテキストはUTF-8エンコードされます。結果はJSONテキスト形式です。定義タイプとしてSQLT_CHR
を使用する場合、JSONテキスト・サイズは32 Kのみに制限されます。SQLT_CHR
からサイズ制限を回避するには、定義変数の型としてSQLT_CLOB
またはSQLT_BLOB
を使用する必要があります。
JSON型の列の問合せ方法を次のコード・スニペットに示します。
void testDescribe()
{
oratext stmt[400] = {0};
ub4 stmtlen;
ub4 numcols;
ub4 i;
OCIStmt *stmthp;
OCIParam *colhd = (OCIParam *) 0;
OCIAuthInfo *authhp = (OCIAuthInfo *)0;
sword status;
getSession(&authhp);
strcpy(stmt, "SELECT jcol FROM jtab where rownum < 2");
stmtlen = strlen(stmt);
Checkerr(errhp,
OCIStmtPrepare2(svchp, &stmthp, errhp, stmt, stmtlen,
(oratext *)0, (ub4)0, (ub4) OCI_NTV_SYNTAX,
(ub4) OCI_DEFAULT), "OCIStmtPrepare2");
printf("\n########### Describe-only test #############\n");
Checkerr(errhp,
OCIStmtExecute(svchp, stmthp, errhp, 0, 0,
(OCISnapshot *)0, (OCISnapshot *)0,
OCI_DESCRIBE_ONLY), "OCIStmtExecute");
/* Get the number of columns in the query */
Checkerr(errhp,
OCIAttrGet((void *)stmthp, OCI_HTYPE_STMT, (void *)&numcols,
(ub4 *)0, OCI_ATTR_PARAM_COUNT, errhp), "OCIAttrGet");
for (i = 1; i <= numcols; i++)
{
ub4 type = 0;
Checkerr(errhp,
OCIParamGet((void *)stmthp, OCI_HTYPE_STMT, errhp,
(void **)&colhd, i), "OCIStmtParamGet");
Checkerr(errhp,
OCIAttrGet((void*)colhd, OCI_DTYPE_PARAM, (void*)&type,
(ub4 *)0, OCI_ATTR_DATA_TYPE, errhp), "OCIAttrGet");
printf("Col %d type %d\n", i, type);
}
releaseSession(authhp);
}
次に、実行を記述する前述のコードの出力で、JSON型の列の型としてBLOBが返されることを示します。
########### Describe-only test #############
Col 1 type 113
23.3 可変DOMと不変DOM
この項では、JSON DOMの可変形式および不変形式について説明します。
OCI記述子を使用すると、可変DOMまたは不変DOMの2つの形式のJSON DOMのいずれかを取得できます。可変DOM内のDOMノードは変更できます。それに対して、不変DOMは読取り専用であり、DOMに対して書込み操作を行うとエラーが発生します。記述子によって保持されるデフォルトのDOMは、OCIAttrSet()
関数を使用してブール属性型に変更されないかぎり、不変です。
ノート:
OCIJsonDomDocSet()
関数を使用して、記述子にJSON DOMコンテナを設定できます。ソースDOMは、記述子の形式と異なる形式にすることができます。つまり、ソースを可変DOMにして、ターゲット記述子に不変DOMを設定できます。
23.3.1 可変DOMとしてのJSONのマニフェスト
OCIクライアント・アプリケーションでは、JSONのコンテンツを可変DOMとしてマニフェストできます。XDKのC DOM関数を使用すると、JSONドキュメントとの間でJSON要素(オブジェクト、配列、スカラーなど)の読取りおよび書込みを行うことができます。
次のコード・スニペットの例は、OCIJson*
記述子との間で可変モードでDOMドキュメントの参照を設定する方法を示しています。
/* Set the JSON DOM MUTABLE Attribute to TRUE */
boolean attr = TRUE;
rc = OCIAttrSet(jsond, /* OCIJson descriptor */
OCI_DTYPE_JSON, /* Descriptor type */
&attr,
OCI_ATTR_JSON_DOM_MUTABLE, /* Attribute type */
errhp);
if (rc != OCI_SUCCESS) goto err_hndlr;
OCI_ATTR_JSON_DOM_MUTABLE
記述子属性にTRUE
を設定するには、OCIAttrSet()
を使用します。
- バッファ入力 –
oratext*
- ストリーミング入力 –
orastream *
23.3.2 不変DOMとしてのJSONのマニフェスト
OCIクライアント・アプリケーションは、バイナリJSONに基づく不変の線形バイナリ・バッファとしてJSONコンテンツをマニフェストできます。
次のコード・スニペットの例は、OCIJson*
記述子との間で不変モードでDOMドキュメントの参照を設定する方法を示しています。この設定を記述子に対して行わない場合は、値FALSE
にデフォルト設定されます。
/* Set the JSON DOM IMMUTABLE Attribute to FALSE */
boolean attr = FALSE;
rc = OCIAttrSet(jsond, /* OCIJson descriptor */
OCI_DTYPE_JSON, /* Descriptor Type */
&attr,
OCI_ATTR_JSON_DOM_MUTABLE, /* Attribute type */
errhp);
if (rc != OCI_SUCCESS) goto err_hndlr;
OCI_ATTR_JSON_DOM_MUTABLE
にFALSE
を設定するには、OCIAttrSet()
を使用します。
- バッファ入力 –
oratext*
- ストリーミング入力 –
orastream *
23.4 JSONデータの書込みおよび読取りのコール順序
この項では、データベースへのJSONデータの書込みおよび読取りのコール順序について説明します。
データベースにJSONデータを書き込むためのコール順序を次の図に示します。
23.5 JSON DOMの操作
この項では、様々なJSON DOMの操作について説明します。
23.5.1 スカラー型のマッピング
この項では、サポートされるスカラー型のマッピングをリストして説明します。
テキストJSONでは、標準JSON言語のスカラー型のみがサポートされます。ただし、JSONデータのSQL型がJSONの場合、Oracle Databaseでは標準のJSON言語型のセットが拡張されており、SQLスカラー・データ型(binary、date、timestamp、double、float、year-month interval、day-second intervalなど)に直接対応する複数のスカラー型が含まれています。
これと同様に、プログラム変数は拡張スカラー型に直接マッピングされるため、OCIJson
を使用してデータベースからJSON値がフェッチされます。これらのプリミティブ型のマッピングのサマリーを次の表に示します。
表23-2 スカラー型のマッピング
JSONスカラー型 | データベースのSQL型 | OCI SQL型定数 | OCIプログラム変数 | JSONスカラー型定数 |
---|---|---|---|---|
|
|
|
oratext[n] |
JZNVAL_STRING |
|
|
|
OCINumber* |
JZNVAL_ORA_NUMBER |
|
該当なし |
該当なし | 該当なし | JZNVAL_TRUE |
|
該当なし | 該当なし | 該当なし | JZNVAL_FALSE |
|
|
|
ub1[n] |
JZNVAL_BINARY |
|
|
|
double |
JZNVAL_DOUBLE |
|
BINARY_FLOAT |
SQLT_BFLOAT |
float |
JZNVAL_FLOAT |
|
|
|
JsonDateTime* |
JZNVAL_ORA_DATE |
|
|
|
JsonDateTime* |
JZNVAL_ORA_TIMESTAMP |
タイムゾーン付きタイムスタンプ |
TIMESTAMP WITH TIMEZONE |
SQLT_TIMESTAMP_TZ |
JsonDateTime* |
JZNVAL_ORA_TIMESTAMPTZ |
|
|
|
JsonDayInterval* |
JZNVAL_ORA_DAYSECOND_DUR |
|
|
|
JsonYearInterval* |
JZNVAL_ORA_YEARMONTH_DUR |
|
該当なし | 該当なし | 該当なし | JZNVAL_NULL |
関連項目:
23.5.2 JSON DOMスカラー・ノードの読取り
この項では、JSON DOMスカラー・ノードを読み取る方法について説明します。
OCIは、バイナリの単精度浮動小数点と倍精度浮動小数点をIEEEの単精度浮動小数点形式および倍精度浮動小数点形式に暗黙的に変換します。number、timestamp、day-second intervalおよびyear-month interval型の場合は、JsonOCIVal *
型を使用し、JsonDomGetScalarInfoOci()
関数を使用して構造化された形式でデータを読み取ることができます。JsonOCIVal *
は、次のコード・スニペットに示されているように定義されたCの共用体です。
/* Auxiliary Union of helper structures */
typedef union JsonOCIVal
{
JsonDateTime dt_JsonOCIVal;
JsonDayInterval dayInv_JsonOCIVal;
JsonYearInterval yrInv_JsonOCIVal;
ub1 num_JsonOCIVal[JZN_ORA_NUM_MAX_LEN];
} JsonOCIVal;
#include <ocijson.h>
void introspectDomNode(appctx *c,
JsonDomDoc *doc,
JsonDomNode *node)
{
JsonOCIVal av;
jznScalarVal sval;
jznnodetype ntype;
/* Check the JSON node type */
ntype = JsonDomGetNodeType(doc, node);
if (ntype == JZNDOM_SCALAR)
{
/* Get information for this JSON scalar node */
JsonDomGetScalarInfoOci(doc, (JsonDomScalar *)node, &sval, &av);
printScalarInfo(c, &sval, &av);
}
else if (ntype == JZNDOM_ARRAY) {...}
else if (ntype == JZNDOM_OBJECT) {...}
...
}
void printScalarInfo(appctx *c,
jznScalarVal *sval,
JsonOCIVal *av)
{
jznvaltype vtype = sval->type_jznScalarVal;
ub4 i;
switch (vtype)
{
case JZNVAL_STRING:
printf("Type: JZNVAL_STRING\n");
printf("Value: %.*s\n", sval->len_jznScalarVal, sval->val_jznScalarVal);
break;
case JZNVAL_BINARY:
printf("Type: JZNVAL_BINARY\n");
printf("Value: ");
for (i = 0 ; i < sval->binlen_jznScalarVal; i++)
printf("%X", (sval->binval_jznScalarVal)[i]);
printf("\n");
break;
case JZNVAL_FLOAT:
printf("Type: JZNVAL_FLOAT\n");
printf("Value: %f\n", sval->flt_jznScalarVal);
break;
case JZNVAL_DOUBLE:
printf("Type: JZNVAL_DOUBLE\n");
printf("Value: %lf\n", sval->db_jznScalarVal);
break;
case JZNVAL_TRUE:
printf("Type: JZNVAL_TRUE\n");
break;
case JZNVAL_FALSE:
printf("Type: JZNVAL_FALSE\n");
break;
case JZNVAL_NULL:
printf("Type: JZNVAL_NULL\n");
break;
case JZNVAL_ORA_NUMBER:
{
double nval;
printf("Type: JZNVAL_ORA_NUMBER\n");
OCINumberToReal(c->errhp, (const OCINumber *) av, (uword) sizeof(nval), &nval);
printf("Value: %d\n", nval);
break;
}
case JZNVAL_ORA_DATE:
{
JsonDateTime *ts;
printf("Type: JZNVAL_ORA_DATE\n");
ts = &(av->dt_JsonOCIVal);
printf("Value: %d-%d-%d\n", ts->year_JsonDateTime, ts->month_JsonDateTime,
ts->day_JsonDateTime);
break;
}
case JZNVAL_ORA_TIMESTAMP:
{
JsonDateTime *ts;
printf("Type: JZNVAL_ORA_TIMESTAMP\n");
ts = &(av->dt_JsonOCIVal);
printf("Value: %d-%d-%d %d:%d:%d:%d\n", ts->year_JsonDateTime,
ts->month_JsonDateTime, ts->day_JsonDateTime, ts->hour_JsonDateTime,
ts->minute_JsonDateTime, ts->second_JsonDateTime,
ts->fsecond_JsonDateTime);
break;
}
case JZNVAL_ORA_TIMESTAMPTZ:
{
JsonDateTime *ts;
printf("Type: JZNVAL_ORA_TIMESTAMPTZ\n");
ts = &(av->dt_JsonOCIVal);
printf("Value: %d-%d-%d %d:%d:%d:%d %03d:%02d\n", ts->year_JsonDateTime,
ts->month_JsonDateTime, ts->day_JsonDateTime, ts->hour_JsonDateTime,
ts->minute_JsonDateTime, ts->second_JsonDateTime,
ts->fsecond_JsonDateTime, ts->tzHourOffset_JsonDateTime,
ts->tzMinuteOffset_JsonDateTime);
break;
}
case JZNVAL_ORA_YEARMONTH_DUR:
{
JsonYearInterval *yint;
printf("Type: JZNVAL_ORA_YEARMONTH_DUR\n");
yint = &(av->yrInv_JsonOCIVal);
printf("Value: %dY-%dM\n",
yint->years_JsonYearInterval, yint->months_JsonYearInterval);
break;
}
case JZNVAL_ORA_DAYSECOND_DUR:
{
JsonDayInterval *dint;
printf("Type: JZNVAL_ORA_DAYSECOND_DUR\n");
dint = &(av->dayInv_JsonOCIVal);
printf("Value: %dD-%dH-%dM-%dS-%dSS\n",
dint->days_JsonDayInterval, dint->hours_JsonDayInterval,
dint->minutes_JsonDayInterval, dint->seconds_JsonDayInterval,
dint->fseconds_JsonDayInterval);
break;
}
default:
printf("ERROR: Unsupported value type encountered [%d]\n", vtype);
break;
}
}
関連項目:
jznScalarValデータ型23.5.3 JSON DOMの作成
この項では、JSON DOMの作成方法について説明します。
23.5.3.1 JSONスカラー型とスカラー・コンストラクタ
この項では、JSONスカラー型および対応するスカラー・コンストラクタを示します。
可変DOMでは、新しいノードを追加したり、既存のノードを変更したりできます。次の表に、スカラー型およびその対応するコンストラクタ関数を示します。
表23-3 スカラー型とコンストラクタ
JSONスカラー型 | スカラー・コンストラクタ |
---|---|
|
|
|
|
|
|
|
|
|
JsonDomCreateBinary |
|
JsonDomCreateDouble |
|
|
|
|
|
|
JZNVAL_ORA_TIMESTAMPTZ |
JsonDomCreateOCIDateTime |
|
|
JZNVAL_ORA_YEARMONTH_DUR |
JsonDomCreateOCIInteval |
JZNVAL_ORA_DAYSECOND_DUR |
JsonDomCreateOCIInteval |
非スカラー型のコンストラクタ関数
次の表に、非スカラー型(配列およびオブジェクト)のコンストラクタ関数を示します。JSONノード・タイプ | スカラー・コンストラクタ |
---|---|
JZNDOM_ARRAY |
JsonDomCreateArray |
JZNDOM_OBJECT |
JsonDomCreateObject |
ノート:
JsonDomSetField()
関数を使用すると、指定したフィールドの値をDOM内の指定したオブジェクトに設定できます。
関連項目:
JSON DOM関数23.5.3.2 スカラー・ノードを使用したDOMの作成
この項では、様々な型のスカラー・ノードを使用してDOMを作成する方法について説明します。
- JSON記述子を割り当て、可変プロパティを設定します
- 様々な型(string、number、boolean、binary、double、float、date、timestamp、null)のスカラー・ノードを作成し、これらのノードをDOMに追加します
- 記述子にJSON DOMコンテナを設定します
- JSON記述子をテキストにシリアライズします
- 記述子を解放します
#include <ocijson.h>
sword buildDom(appctx *c,
JsonDomDoc *jdoc,
JsonDomObject *root,
boolean ismut)
{
OCIJson *jsond;
oratext outbuf[1024] = {0};
oraub8 outlen = 1024;
JsonDomScalar *node;
/* Field names */
oratext *s_name = (oratext *) "string_val";
oratext *n_name = (oratext *) "number_val";
oratext *bt_name = (oratext *) "true_val";
oratext *bf_name = (oratext *) "false_val";
oratext *b_name = (oratext *) "binary_val";
oratext *d_name = (oratext *) "double_val";
oratext *f_name = (oratext *) "float_val";
oratext *dt_name = (oratext *) "date_val";
oratext *dtt_name = (oratext *) "datetime_val";
oratext *dttz_name = (oratext *) "datetimetz_val";
oratext *yminv_name = (oratext *) "yminterval_val";
oratext *dsinv_name = (oratext *) "dsinterval_val";
oratext *nl_name = (oratext *) "null_val";
/* Values */
oratext *sval = (oratext *) "Strings are sequence of characters";
ub4 slen = (ub4) strlen(sval);
int inval = -29873546;
OCINumber nval;
boolean btval = TRUE;
boolean bfval = FALSE;
ub1 bval[8] = {0x000D, 0x000E, 0x000A, 0x000D,
0x000B, 0x000E, 0x000E, 0x000F};
ub4 blen = (ub4) 8;
double dval = 34837749.5699837;
float fval = -133424.75;
OCIDate *odval = NULL;
sb2 yrval = 2020;
ub1 mnval = 10;
ub1 dyval = 25;
OCIDateTime *odtval = NULL;
ub1 hrval = 8;
ub1 minval = 32;
ub1 secval = 56;
ub4 fsecval = 123456789;
OCIDateTime *odtzval = NULL;
oratext *tzone = (oratext *)"-05:30";
ub4 tzlen = (ub4) strlen(tzone);
OCIInterval *yminval = NULL;
oratext *yminvt = (oratext *)"04-11";
OCIInterval *dsinval = NULL;
oratext *dsinvt = (oratext *)"11 10:36:19.000005";
/* (1) Allocate JSON descriptor and set mutable property */
checkerr("Allocate JSON descriptor", c,
OCIDescriptorAlloc(c->envhp, (void **) &jsond,
OCI_DTYPE_JSON, 0, 0));
checkerr("Attr set mutable", c,
OCIAttrSet((void *) jsond, OCI_DTYPE_JSON, &ismut, 0,
OCI_ATTR_JSON_DOM_MUTABLE, c->errhp));
/* (2) Create scalar fields and add to DOM */
/* (a) Add string field */
node = JsonDomCreateString(jdoc, sval, slen);
JsonDomSetField(jdoc, root, s_name, (ub2) strlen(s_name),
(JsonDomNode *) node);
/* (b) Add number field */
checkerr("Create OCINumber", c,
OCINumberFromInt(c->errhp, &inval, sizeof(int), OCI_NUMBER_SIGNED,
&nval));
node = JsonDomCreateOCINumber(jdoc, &nval);
JsonDomSetField(jdoc, root, n_name, (ub2) strlen(n_name),
(JsonDomNode *) node);
/* (c) Add boolean TRUE field */
node = JsonDomCreateBoolean(jdoc, btval);
JsonDomSetField(jdoc, root, bt_name, (ub2) strlen(bt_name),
(JsonDomNode *) node);
/* (d) Add boolean FALSE field */
node = JsonDomCreateBoolean(jdoc, bfval);
JsonDomSetField(jdoc, root, bf_name, (ub2) strlen(bf_name),
(JsonDomNode *) node);
/* (e) Add binary field */
node = JsonDomCreateBinary(jdoc, bval, blen);
JsonDomSetField(jdoc, root, b_name, (ub2) strlen(b_name),
(JsonDomNode *) node);
/* (f) Add double field */
node = JsonDomCreateDouble(jdoc, dval);
JsonDomSetField(jdoc, root, d_name, (ub2) strlen(d_name),
(JsonDomNode *) node);
/* (g) Add float field */
node = JsonDomCreateFloat(jdoc, fval);
JsonDomSetField(jdoc, root, f_name, (ub2) strlen(f_name),
(JsonDomNode *) node);
/* (h) Add date field */
checkerr("Create OCIDate", c,
OCIDescriptorAlloc(c->envhp, (void **) &odval, OCI_DTYPE_DATE,
0, NULL));
OCIDateSetDate(odval, yrval, mnval, dyval);
node = JsonDomCreateOCIDate(jdoc, odval);
JsonDomSetField(jdoc, root, dt_name, (ub2) strlen(dt_name),
(JsonDomNode *) node);
/* (i) Add datetime field */
checkerr("Create OCIDateTime", c,
OCIDescriptorAlloc(c->envhp, (void **) &odtval, OCI_DTYPE_TIMESTAMP,
0, NULL));
checkerr("Construct OCIDateTime timezone", c,
OCIDateTimeConstruct (c->envhp, c->errhp, odtval,
yrval-10, mnval-5, dyval-10,
hrval, minval, secval, fsecval, NULL, 0));
node = JsonDomCreateOCIDateTime(jdoc, odtval);
JsonDomSetField(jdoc, root, dtt_name, (ub2) strlen(dtt_name),
(JsonDomNode *) node);
/* (j) Add datetime timezone field */
checkerr("Create OCIDateTime timezone", c,
OCIDescriptorAlloc(c->envhp, (void **) &odtzval, OCI_DTYPE_TIMESTAMP_TZ,
0, NULL));
checkerr("Construct OCIDateTime timezone", c,
OCIDateTimeConstruct (c->envhp, c->errhp, odtzval,
yrval-7, mnval-3, dyval-2,
hrval-1, minval-10, secval-25, fsecval-98765432,
tzone, tzlen));
node = JsonDomCreateOCIDateTime(jdoc, odtzval);
JsonDomSetField(jdoc, root, dttz_name, (ub2) strlen(dttz_name),
(JsonDomNode *) node);
/* (k) Add year-month interval field */
checkerr("Create OCIInterval year-month", c,
OCIDescriptorAlloc(c->envhp, (void **) &yminval, OCI_DTYPE_INTERVAL_YM,
0, NULL));
checkerr("Construct OCIInterval year-month", c,
OCIIntervalFromText(c->envhp, c->errhp, yminvt, strlen(yminvt), yminval));
node = JsonDomCreateOCIInterval(jdoc, yminval);
JsonDomSetField(jdoc, root, yminv_name, (ub2) strlen(yminv_name),
(JsonDomNode *) node);
/* (l) Add day-second interval field */
checkerr("Create OCIInterval day-second", c,
OCIDescriptorAlloc(c->envhp, (void **) &dsinval, OCI_DTYPE_INTERVAL_DS,
0, NULL));
checkerr("Construct OCIInterval day-second", c,
OCIIntervalFromText(c->envhp, c->errhp, dsinvt, strlen(dsinvt), dsinval));
node = JsonDomCreateOCIInterval(jdoc, dsinval);
JsonDomSetField(jdoc, root, dsinv_name, (ub2) strlen(dsinv_name),
(JsonDomNode *) node);
/* (m) Add NULL field */
node = JsonDomCreateNull(jdoc);
JsonDomSetField(jdoc, root, nl_name, (ub2) strlen(nl_name),
(JsonDomNode *) node);
/* (3) Set the JSON DOM container in the descriptor */
checkerr("Set JSON DOM container", c,
OCIJsonDomDocSet(c->svchp, jsond, jdoc, c->errhp, 0));
/* (4) Serialize JSON descriptor to text */
checkerr("To Text Buffer", c,
OCIJsonToTextBuffer(c->svchp, jsond, outbuf, &outlen,
JZNU_PRINT_PRETTY, c->errhp,
OCI_JSON_TEXT_ENV_NLS));
printf("Descriptor content:\n");
printf("%.*s \n", outlen, outbuf);
finally:
/* (5) Free the descriptors */
if (odval)
checkerr("Free Date descriptor", c,
OCIDescriptorFree(odval, OCI_DTYPE_DATE));
if (odtval)
checkerr("Free DateTime descriptor", c,
OCIDescriptorFree(odtval, OCI_DTYPE_TIMESTAMP));
if (odtzval)
checkerr("Free DateTime timezone descriptor", c,
OCIDescriptorFree(odtzval, OCI_DTYPE_TIMESTAMP_TZ));
if (yminval)
checkerr("Free Interval year-month descriptor", c,
OCIDescriptorFree(yminval, OCI_DTYPE_INTERVAL_YM));
if (dsinval)
checkerr("Free Interval day-second descriptor", c,
OCIDescriptorFree(dsinval, OCI_DTYPE_INTERVAL_DS));
if (jsond)
checkerr("Free JSON descriptor", c,
OCIDescriptorFree(jsond, OCI_DTYPE_JSON));
return c->status;
}
関数printScalarInfo()
の出力は次のとおりです。
ノート:
すべてのタイプ情報が保持されますKey: "string_val"
Type: JZNVAL_STRING
Value: Strings are sequence of characters
Key: "number_val"
Type: JZNVAL_ORA_NUMBER
Value: -29873546.000000
Key: "true_val"
Type: JZNVAL_TRUE
Key: "false_val"
Type: JZNVAL_FALSE
Key: "binary_val"
Type: JZNVAL_BINARY
Value: DEADBEEF
Key: "double_val"
Type: JZNVAL_DOUBLE
Value: 34837749.569984
Key: "float_val"
Type: JZNVAL_FLOAT
Value: -133424.750000
Key: "date_val"
Type: JZNVAL_ORA_DATE
Value: 2020-10-25
Key: "datetime_val"
Type: JZNVAL_ORA_TIMESTAMP
Value: 2010-5-15 8:32:56:123456789
Key: "datetimetz_val"
Type: JZNVAL_ORA_TIMESTAMPTZ
Value: 2013-7-23 7:22:31:24691357 -05:-30
Key: "yminterval_val"
Type: JZNVAL_ORA_YEARMONTH_DUR
Value: 4Y-11M
Key: "dsinterval_val"
Type: JZNVAL_ORA_DAYSECOND_DUR
Value: 11D-10H-36M-19S-5000SS
Key: "null_val"
Type: JZNVAL_NULL
OCIJsonToTextBuffer()
関数は、次のテキストJSONの出力を戻します。
ノート:
拡張型は失われ、文字列に変換されます。{
"true_val" : true,
"number_val" : -29873546,
"string_val" : "Strings are sequence of characters",
"date_val" : "2020-10-25T00:00:00",
"dsinterval_val" : "P11DT10H36M19.000005S",
"yminterval_val" : "P4Y11M",
"datetime_val" : "2010-05-15T08:32:56.123456789",
"binary_val" : "0D0E0A0D0B0E0E0F",
"null_val" : null,
"false_val" : false,
"datetimetz_val" : "2013-07-23T07:22:31.024691357-05:30",
"float_val" : -133424.75,
"double_val" : 34837749.5699837
}
関連項目:
JSON DOM関数23.6 JSON記述子を使用したマルチスレッド
OCIJson
*記述子はスレッド・セーフではありません。記述子とその子孫のDOMノードが一度に1つのスレッドのみで操作されるようにすることは、ユーザーの責任です。
23.7 文字セットの処理
OCIでは、テキスト入力の文字セットは、OCI環境ハンドルの設定によって異なります。
OCIEnv*
の作成時にユーザーがcsid
パラメータを指定しない場合、NLS_LANG
設定がハンドルのデフォルト設定として使用されます。テキストJSONが入力であるOCIJsonTextBufferParse()
、OCIJsonTextStreamParse()
などのAPIの場合、入力は、Oracleで認識される任意の文字セットにすることができ(JSON構文に準拠している場合)、環境ハンドルまたはNLS_LANG
パラメータに設定されている文字セットである必要はありません。
ノート:
Unicodeでエンコードされた入力にJZN_INPUT_DETECT
を使用する場合、入力のエンコーディングはUTF-8、UTF-16 (LEまたはBE)のいずれかとして検出され、それに応じて処理されます。テキストJSONの入力がこのモードのUnicodeのエンコーディングのいずれかではない場合は、ユーザー・エラーであり、動作は保証されません。
OCI_JSON_TEXT_ENV_NLS
モードが設定されている場合を除き、OCIJson API (OCIJsonToTextBuffer ()
、OCIJsonToTextStream ()
など)は、テキストJSONをAL32UTF8文字セットで戻します。
23.8 スキーマ検証のOCIインタフェース
OCIアプリケーションでJSONスキーマ検証を実行するためのOCIインタフェース。
用途
JSONスキーマに対してJSONドキュメント・インスタンスを検証します。詳細なエラー・メッセージは、エラーJSON記述子のJSONインスタンスとして報告されます。
構文
sword OCIJsonSchemaValidate (
OCISvcCtx *svchp,
OCIJson *jsond,
OCIJson *schemad,
ub4 sflags,
OCIJson *errors,
ub1 errmode,
OCIError *errhp,
ub4 mode
);
パラメータ
関連項目:
JSONスキーマ23.9 列にJSONスキーマ制約があるかどうかを確認する属性
OCI属性OCI_ATTR_HAS_JSON_SCHEMA
は、列にJSONスキーマ制約があるかどうかをチェックします。
例23-1 OCI_ATTR_HAS_JSON_SCHEMA属性の使用
SYNTAX
ub1 has_schema;
tkpgjsCheck("Get ith column handle", c,
OCIParamGet(collsthd, OCI_DTYPE_PARAM, c->errhp,
(void **) &colhd, i));
tkpgjsCheck("OCI_ATTR_HAS_JSON_SCHEMA", c,
OCIAttrGet(colhd, OCI_DTYPE_PARAM, &has_schema, (ub4 *)0,
OCI_ATTR_HAS_JSON_SCHEMA, c->errhp));
printf("OCI_ATTR_HAS_JSON_SCHEMA: %d\n", has_schema);