5 SQL/JSON条件IS JSONおよびIS NOT JSON

SQL/JSON条件is jsonおよびis not jsonは補足的な条件です。これらは、引数が構文的に正しい(つまり、整形式の)JSONデータかどうかをテストします。オプションのキーワードVALIDATEによって、データが特定のJSONスキーマに関しても有効かどうかをテストします。

is jsonis not jsonは、CASE式またはSELECT文のWHERE句で使用できます。is jsonはチェック制約で使用できます。

テストしたデータが構文的に正しいときに、キーワードVALIDATEが存在しない場合、is jsonはtrueを返し、is not jsonはfalseを返します。

キーワードVALIDATEが存在する場合、データは指定されたJSONスキーマに関して整形式かつ有効であること(またはでないこと)を確認するためにテストされます。キーワードVALIDATE (オプションでキーワードUSINGが続く)の後には、検証対象のJSONスキーマであるSQL文字列リテラルが続く必要があります。

JSON型データの場合、データがオブジェクト、配列またはスカラー値であることのみをチェックする単純なJSONスキーマでVALIDATEを使用するかわりに、キーワードOBJECTARRAYまたはSCALARをそれぞれ使用できます。たとえば、次の条件は、データがオブジェクトであるかどうかをテストします:

is json OBJECT

修飾子キーワードSCALARの後には、スカラーの必要な型を指定するキーワードBOOLEANBINARYBINARY_DOUBLEBINARY_FLOATDATEINTERVAL DAY TO SECOND INTERVAL YEAR TO MONTHNULLNUMBERSTRINGTIMESTAMPまたはTIMESTAMP WITH TIME ZONEを続けることができます。

また、複数のJSON型修飾子を使用することもできます。その場合は、カンマで区切ってリストをカッコで囲みます。たとえば、(OBJECT, SCALAR DATE)ではオブジェクトまたは日付のみが許可され、次の2つの等価条件では、データがオブジェクトまたはスカラー値のどちらであるかがテストされます:

is json (OBJECT, SCALAR)
is not json ARRAY

ノート:

is jsonでのJSON型修飾子の使用は、JSON型列の作成時にそれを使用する場合よりも制限されています。is jsonの場合:

  • 修飾子キーワードLIMITは使用できません。

  • 修飾子キーワードARRAYの後に続けて、構文をカッコで囲んで、使用可能な配列値をさらに指定することはできません。

JSON型修飾子キーワードを他のキーワードと組み合せて使用できます。(修飾子キーワードが最初に来る必要があります。)ただし、修飾子キーワードの効果が、is json SCALAR DISALLOW SCALARSの指定など、存在する他のキーワードの効果と競合する場合は、エラーが発生します。

is jsonがチェック制約として使用されている場合、JSON型修飾子キーワードは使用できません:

CREATE TABLE t1 (c1 JSON CHECK (c1 is json OBJECT));
CREATE TABLE t1 (c1 JSON CHECK (c1 is json OBJECT))
                                           *
ERROR at line 1:
ORA-02252: check constraint condition not properly ended

is (not) JSON条件の解析(または検証)中にエラーが検出された場合、エラーが発生することはなく、データは整形式でない(または有効でない)とみなされます。is jsonはfalseを返し、is not JSONはtrueを返します。(解析中または検証中以外にエラーが検出された場合は、そのエラーが発生します)。

整形式のデータとは、構文的に正しいデータであることを意味します。テキストとして格納されているJSONデータは、厳密な構文と緩慢な構文と呼ばれる2つの意味での整形式にすることができます。また、テキストのJSONデータの場合は、JSONオブジェクトに重複したフィールド(キー)を含めることができるかどうかを指定できます。

anyデータ型(テキストまたはJSON型)のJSONデータの場合:

  • 整形式のデータの文書に最上位レベルのスカラー値を含めることができるかどうかを指定できます(データベース初期化パラメータcompatible20以上の場合)。また、有効である必要があることも指定できます。

  • 特定のJSONスキーマに対して、データを検証する必要があること(またはis not JSONによって、その必要がないこと)を指定できます。

テキストのJSONデータがデータベース内で生成される場合は、キーワードSTRICTを指定した条件is jsonを満たします。これには次の方法による生成が含まれます。

  • SQL/JSON生成関数の使用(FORMAT JSONでキーワードSTRICTを指定する場合を除きます。指定する場合は、データがJSONデータであることを宣言する意味があり、ユーザーがそれを保証するため、整形式であるかどうかはチェックされません)

  • SQLファンクションjson_serializeの使用

  • SQL/JSONファンクションjson_queryの使用

  • FORMAT JSONを指定したSQL/JSONファンクションjson_tableの使用

  • PL/SQL DOMでのPL/SQLメソッドto_clob()to_blob()またはto_string()の使用

ノート:

JSON型のデータは一意のオブジェクト・キー(フィールド名)のみを持ち、厳密な構文と緩慢な構文の概念は適用されません。(任意のデータ型の) JSONデータをシリアライズしてテキストJSONデータを生成する場合、結果の構文は常に厳密です。

JSONデータ型を使用してJSONデータを格納し、is jsonチェック制約を使用する場合、次のようになります。

  • キーワードDISALLOW SCALARSを指定した場合、JSON列には最上位レベルのスカラーJSON値を持つ文書を格納できません。

  • キーワードを指定しない場合、またはDISALLOW SCALARS以外のキーワードを指定した場合、is json制約は無視されます。それらのキーワードでは何も変更されません。

キーワードCHECKおよびIS JSONは省略できます。たとえば、次の2つのチェック制約は同等であり、どちらも、列jcolの値がJSON文字列であることを確認します:

CHECK (jcol is json VALIDATE '{"type": "string"}')
jcol VALIDATE '{"type": "string"}'

_________________________________________________________

関連項目:

  • is jsonおよびis not jsonの詳細は、『Oracle Database SQL言語リファレンス』「IS JSON条件」を参照してください。

  • JSONスキーマの詳細は、json-schema.orgを参照してください

5.1 JSONオブジェクトの一意フィールドと重複フィールド

JSON標準では、JSONオブジェクトに重複するフィールド名がないことが推奨されています。Oracle Databaseでは、エラーを発行することでJSON型のデータに対してこれが強制されます。テキスト形式で格納されている場合は、キーワードWITH UNIQUE KEYSを指定したis jsonチェック制約を使用して、重複するフィールド名を許可しないことをお薦めします。

テキスト(VARCHAR2CLOBBLOB列)で格納されている場合、重複する名前のチェックに時間がかかるため、デフォルトでは、JSONデータの重複するフィールド名が許可されています。テキストで格納されたJSONデータのこのデフォルトの動作によって一貫性のない動作になる可能性があるため、デフォルトには依存しないことをお薦めします。

このデフォルトの動作をオーバーライドして、フィールドが重複しているオブジェクトを含むデータを挿入しようとしたときにエラーが発生するようにできます。これを行うには、キーワードWITH UNIQUE KEYSを指定してis jsonチェック制約を使用します。(これらのキーワードは、JSON型の列に挿入されるデータには影響しません。)

整形式のテキストJSONデータで重複フィールド名が許可されるかどうかは、整形式かどうかの確認に、厳密な構文と緩慢な構文のどちらが使用されるかとかかわっています。

5.2 厳密なJSON構文と緩慢なJSON構文

入力時には、JSONのOracleのデフォルト構文は緩慢です。この構文は、オブジェクト・フィールドに対してJavaScript構文を反映し、ブール型の値およびnull値では大/小文字が区別されず、数字、ホワイトスペースおよびUnicode文字のエスケープについてはより寛容です。Oracleは、標準に厳密に準拠したJSONデータを出力します

標準IETF RFC 8259ECMA 404およびECMA 262では、JSON構文が定義さています。Oracleでは、この厳密なJSON構文がサポートされており、出力時には必ずそれが使用されますが、入力時にデータを解析するときは緩慢な構文が使用されます。

これらの仕様(ECMAScript第5.1版より前)によると、各JSONフィールドおよび各文字列値は、二重引用符(")で囲む必要があります。しかしながら、JavaScript表記法では、オブジェクト・リテラルで使用されるフィールドは二重引用符で囲むことはできますがそれは必須ではありません。これはまた、一重引用符(')で囲むこともできます。

ECMA 262, 5.1 Editionでは、このようなフィールドを許可するなど、いくつかの方法で厳密な構文が緩和されました。Oracleの緩慢なJSON構文では、ECMAScript 5.1で指定されている構文がサポートされています。より一般的に述べると、Oracleの緩慢な構文では、一重引用符は二重引用符と同様に、複数の文字列を区切るための文字です。

また、Oracleの緩慢な構文では、ECMAScript 5.1で指定されている内容とは異なり、エスケープされていない行および段落セパレータ文字(U+2028およびU+2029)をJSON文字列に含めることができます。(これはJSON5の場合も同様で、この違いを除けば、ECMAScript 5.1の適切なサブセットです。)

さらに、実際には、一部のJavaScript実装では次の1つ以上が許可されています:

  • truefalseおよびnullの大/小文字の相違(TRUETrueTrUefALSeNulLなど)。

  • 配列の最後の要素またはオブジェクトの最後のメンバーの後に追加される単一のカンマ(,) ([a, b, c,]{a:b, c:d,}など)。(これは、ECMAScript 5.1でも許可されます。)

  • 先頭に1つ以上の0がある数字(0042.3など)。

  • 小数点の前に0がない小数(0.14ではなく.14など)。

  • 小数点の後に小数部分がない数字(342.1.e27など)。

  • 数値がマイナスではないことを意味する、数字の前のプラス記号(+) (+1.3など)。

この構文も、Oracleの緩慢なJSON構文の一部として、入力時に許可されます。(厳密な数字構文は、JSON標準を参照してください。)

ASCIIのスペース文字(10進数の32、U+0020)以外にも、JSON標準では、引用符で囲まれたフィールドまたは文字列値の外側で使用される場合、次のASCII文字は重要でないホワイトスペース(つまり無視される)として定義されています。

  • タブ、水平タブ(HT ^I、10進数の9、U+0009、\t)

  • 行送り、改行(LF ^J、10進数の10、U+000A、\n)

  • キャリッジ・リターン(CR ^M、10進数の13、U+000D、\r)

ただし、Oracleの緩慢なJSON構文では、すべてのASCII制御文字(制御文字0-31)は重要でないホワイトスペースとして処理されます。制御文字には次のようなものがあります。

  • Null (NUL ^@、10進数の0、U+0000、\0)

  • ベル(NEL ^G、10進数の7、U+0007、 \a)

  • 垂直タブ(VT ^K、10進数の11、U+000B)

  • エスケープ(ESC ^[、10進数の27、U+001B、\e)

  • 削除(DEL ^?、10進数の127、U+007F)

Oracleの厳密なJSON構文では、すべてのASCIIのホワイトスペース文字は重要でないものとして扱われ、ASCIIのスペース文字(U+0020)は、引用符で囲まれたフィールドまたは文字列値内で許可され、エスケープされない唯一のホワイトスペース文字です。Oracleの緩慢な構文では、ECMAScript 5.1と同様に、すべてのUnicodeのホワイトスペース文字は重要でないものとして扱われます。

Oracleの緩慢なJSON構文では、引用符で囲まれていないオブジェクト・フィールド名に、次を除いたエスケープされていないUnicode文字を含めることができます(ただし、エスケープ・シーケンスは許可されません):

  • ホワイトスペース、つまりホワイトスペース・プロパティを持つUnicode文字。『Unicode character property, Whitespace』を参照してください。

  • JSON構造文字: 左右の角カッコ([])および波カッコ({})、コロン(:)およびカンマ(,)。

  • 斜線(スラッシュとも呼ばれる、/)。これは、/*がECMAScript 5.1とOracleの緩慢な構文の両方でJSONコメント(*/で終了)を開始するため、許可されません。

  • 逆斜線(バックスラッシュとも呼ばれる、\)。これはエスケープ・シーケンスを導入するため、許可されません。

  • 一重引用符および二重引用符('")。これらは文字列デリミタとして機能するため、許可されません。

厳密なJSON構文と緩慢なJSON構文の両方で、引用符で囲まれたオブジェクト・フィールド名およびその他の文字列値に任意のUnicode文字を含めることができます。それぞれの文字を含めるには、ASCIIエスケープ構文\uの後にUnicodeコード・ポイントを表す4つのASCII 16進数を続けます。

次のUnicode文字は、\uの後にコード・ポイントまたは特殊なエスケープ・シーケンスが続くフィールド名および文字列で表される必要があります

  • ASCII制御文字のバックスペース(CONTROL-H)、フォームフィード(CONTROL-L)、改行(行送り)、キャリッジリターン(CONTROL-M)、および(水平)タブ(CONTROL-I)。

    \b (バックスペース)、\f (フォーム・フィード)、\n (改行)、\r (キャリッジリターン)および\t (タブ)を使用します。

  • 逆斜線(バックスラッシュとも呼ばれる) \および二重引用符"

    これらをエスケープするには、それぞれの前に逆斜線文字を付けます: \\および\"。(必要ではありませんが、斜線/スラッシュ文字を同じ方法でエスケープできます: \/。)

表5-1は、JSON構文のいくつかの例を示しています。

表5-1 JSONオブジェクト・フィールドの構文例

整形式かどうか

"part number": 1234

緩慢および厳密: はい。スペース文字は許可されます。

part number: 1234

緩慢(および厳密): いいえ。引用符で囲まれていない名前では、スペース文字を含むホワイトスペース文字は許可されません。

"part\tnumber": 1234

緩慢および厳密: はい。タブ文字のエスケープ・シーケンスは許可されます。

"part    number": 1234

緩慢: はい、厳密: いいえ。エスケープされていないタブ文字は、緩慢な構文でのみ使用できます。厳密な構文で許可されるエスケープされていないホワイトスペース文字は、スペース(U+0020)のみです。

"\"part\"number": 1234

緩慢および厳密: はい。名前が引用符で囲まれている場合、エスケープされている二重引用符は許可されます。

\"part\"number: 1234

緩慢および厳密: いいえ。二重引用符を埋め込むには、フィールド名を引用符で囲む必要があります。

'\"part\"number': 1234

緩慢: はい、厳密: いいえ。一重引用符で囲まれた名前(オブジェクト・フィールドと文字列)は、緩慢な構文でのみ許可されます。引用符で囲まれた名前では、エスケープされている二重引用符が許可されます。

"'part'number": 1234

緩慢: はい、厳密: いいえ。一重引用符は、緩慢な構文の文字列内で(のみ)、許可され、エスケープされません。

"pärt : number":1234

緩慢および厳密: はい。引用符で囲まれた名前では、任意のUnicode文字が許可されます。これには、ホワイトスペース文字と、コロン(:)などの、JSONの構造的な文字が含まれます。

part:number:1234

緩慢(および厳密): いいえ。引用符で囲まれている名前では、構造文字は許可されません。

ノート:

このドキュメントでは次の2つの異なる方法で"厳密"と"緩慢"が使用されています。これらを混同しないでください:

  • 厳密または緩慢な構文のチェック。これは、入力時などの、テキストJSONデータの解析方法について言及しています。

    厳密な構文では、JSON標準が完全に尊重されます。緩慢な構文では、引用符なしのフィールド名が許可されているなど、いくつかの点で標準から逸脱したデータが受け入れられます。

    厳密な構文と緩慢な構文については、「厳密なJSON構文と緩慢なJSON構文」を参照してください。

  • 厳密または緩慢な型互換性。これは、JSON値をそれらのJSON言語型に関して厳密に比較するかどうかに言及しています。

    厳密な型互換性では、値が、想定している型と同じJSON言語型ファミリである必要があります。たとえば、想定している型がnumberである場合、互換性のある値は、数値である必要があります。緩慢な型互換性では、値を、想定している型に変換しようとします。たとえば、文字列"42"は、型numberと緩慢な互換性があります。

    厳密な型互換性と緩慢な型互換性については、「SQLファンクションおよび条件のTYPE句」を参照してください。

関連項目:

5.3 条件IS JSONでの厳密なJSON構文の指定

Oracle Databaseでは、デフォルトで、JSONデータの解析時に緩慢な構文が使用されます。必ずテキストJSONデータが厳密になるようにするには、キーワード(STRICT) (カッコを含む)を指定して条件is jsonを使用します。

例5-1 テキストのJSONデータが厳密な整形式であることを確認するためのチェック制約でのIS JSONの使用

JSON列dataのデータ型はVARCHAR2です。そのデータはテキストであるため(JSON型ではない)、is jsonチェック制約が必要です。キーワードSTRICTは、厳密な(つまり、標準)JSON構文であることを必須とするために使用されています。脚注1

CREATE TABLE j_purchaseorder
  (id          VARCHAR2 (32) NOT NULL PRIMARY KEY,
   date_loaded TIMESTAMP (6) WITH TIME ZONE,
   data        VARCHAR2 (32767)
   CONSTRAINT ensure_json CHECK (data is json (STRICT)));

キーワードSTRICTの追加を除き、これは例4-2と同じです(その例では、整形式のJSONデータを必要としているが、その構文は緩慢でも厳密でもかまわない)

関連項目:

『Oracle Database SQL言語リファレンス』「CREATE TABLE」



脚注の凡例

脚注1: IS NOT JSON (STRICT)を使用すると、一部のテキスト・データが厳密に整形式のJSONではないことをチェックできます。