Oracle DatabaseでのJSON strictおよびlax構文| Pt 1: JSONの格納 (2025/02/04)

Oracle DatabaseでのJSON strictおよびlax構文| Pt 1: JSONの格納 (2025/02/04)

https://blogs.oracle.com/developers/post/building-excitement-with-oracle-appdev-in-2025

投稿者: Martin Bach


JSONでは、lax構文と厳密な構文の両方がサポートされています。しかし、これはどういう意味ですか? こちらの2つの記事でご覧いただけます! ここでは、JSONの記述と格納について説明します。また、JSONのテキスト表現にも適用されます。Oracle Database 21c以降では、ネイティブJSONデータ型がサポートされており、読み取ろうとしている記事全体が、21cより前のリリース(19c以前)に適用されます。Oracle Database 23aiを使用している場合は、かわりにネイティブJSONデータ型を使用してください。また、テキストJSON表現から既存のスキーマのネイティブ・データ型への移行も強く検討できます。



JSON laxおよび厳密な構文


JSON開発者ガイドによると、laxとstrict JSONのトピックには2つの側面があります。


  • JSONをデータベース列として格納する場合
  • JSON_QUERYなどのJSONファンクションの一部として型変換を実行します。


将来の記事で型変換に飛び込む前に、JSONを格納する最初の例を見てみましょう。繰り返しになりますが、これは主にOracle Database 19cに適用され、新しいリリースには専用のJSONデータ型が搭載されているため、生活が大幅に楽になります。



表へのJSONの格納


Oracle Databaseは、10年以上前にリリースされたデータベース・リリース12c以降、JSONをサポートしています。それ以来、多くのことが起こり、Oracle Database 21cにJSON用の新しい専用データ型が導入されました。OSON JSONデータ型に関心がある場合は、データベース内の他のJSONデータ型実装との比較など、このMedium記事で想像できるすべての詳細がわかります。



データベース・リリース21cより前のリリースのJSON列


Oracle Database 21cより前のリリースでは、JSONはテキスト(VARCHAR2、BLOBまたはCLOB列)として格納されていました。これは、慎重でない場合、任意のコンテンツ、および構文的に正しくないJSONを表に格納できることを意味します。


以下の例はデモンストレーションのみを目的としており、自宅でも行わないでください。


create table t1 (
    id number generated by default on null as identity
    constraint pk_t1 primary key,
    json_column clob
);


セーフティーネットがないと、無効なJSONを挿入できます。


SQL> insert into t1 ( json_column ) values ( 'this is not valid json' );

1 row inserted.

SQL> rollback;

Rollback complete


有効なJSONのみを保存するには、次の例に示すように、JSONテキスト列にチェック制約を追加します。


alter table t1 add constraint c_t1_json check (json_column is json);


これは、意図した内容とほぼ一致している可能性が高く、Oracle Database 19c以前では、このチェック制約なしでJSONを格納したくないことは間違いありません。Oracle Database 21c以降でネイティブJSONデータ型を使用する場合、正しくないJSONについて心配する必要はありません。これは拒否されます。


書込み操作中に無効なJSONを捕捉する必要があり、これがチェック制約の動作です。


SQL> insert into t1 ( json_column ) values ( 'this is not valid json' );

Error starting at line : 1 in command -
insert into t1 ( json_column ) values ( 'this is not valid json' )
Error report -
ORA-02290: check constraint (MARTIN.C_T1_JSON) violated


無効なJSONが拒否されました。有効なJSONパスのみ:


SQL> insert into t1 (json_column) values ('{ valid: true }');

1 row inserted.

SQL> insert into t1 (json_column) values ('{ valid: true, someString: "some string", someNumber: 1234 }');

1 row inserted.


でも、待って、それ以上のものがある!



テキストJSON表現の厳密な構文とLax構文


前述のinsert文は、いわゆるlax構文を使用して記述されています。この例では、標準で義務付けられているルールに違反しています。各JSONフィールドおよび各文字列値は二重引用符で囲む必要があります。


明らかに、前述の例ではそうではありません。


SQL> select json_column from t1;

JSON_COLUMN                                                     
_______________________________________________________________ 
{ valid: true }                                                 
{ valid: true, someString: "some string", someNumber: 1234 }


"textual" JSONを格納する場合、データベースは書き込み時にドキュメントを変更しません。上記は依然として有効なJSONですが、すべての開発ツールがそれに細かい線を加えます。これらのJSONドキュメントを格納できることはバグではありません。実際には、ドキュメントに従って意図された動作です。


入力時、JSONのOracleのデフォルトの構文はlaxです。オブジェクト・フィールドのJavaScript構文が反映され、ブール値とnull値は大/小文字が区別されず、Unicode文字の数値、空白およびエスケープに関してより許容されます。Oracle関数は、標準を厳密に尊重するJSONデータを返します。


それはどういう意味ですか。前述の例では、厳密な構文ルールに従わないCLOB列にJSONを挿入できることがわかります。ただし、json_serializeなどの関数を使用して表にアクセスすると、Oracle関数は厳密な構文ルールに準拠したJSONを返すことがわかります。


SQL> select
  2    id,
  3    json_serialize(j.json_column pretty) as strict_json
  4  from
  5*  t1 j;

   ID STRICT_JSON                                                                    
_____ ______________________________________________________________________________ 
    1 {
        "valid" : true
      }                                                           
    2 {
        "valid" : true,
        "someString" : "some string",
        "someNumber" : 1234
      }


二重引用符で囲まれたフィールドは、someStringおよびsomeNumberが有効であることに注意してください。



テキストJSONに対する厳密な構文ルールの強制


この時点で、すべての例がJSONをCLOBとして格納すること、つまりテキスト表現に基づいていることを指摘することが重要です。Oracle Database 21cから始めて、自分自身を繰り返すリスクがある場合は、新しいJSONデータ型を実際に使用する必要があります。


Oracle Database 23aiへの移行をまだ行っていない場合でも、書込み時に厳密なJSONを強制できます。


前に示したis jsonチェック制約は、開発者が有効なJSONのみを受け入れることを意図していると宣言しています。これをさらに一歩進めるには、厳密なJSONも必要です。


create table t2 (
    id number generated by default on null as identity
    constraint pk_t2 primary key,
    json_column clob,
    constraint c_t2_json check (json_column is json (strict))
);


これで事実上無効になりました。


  • 無効なJSON
  • JSONが厳密な構文ルールに準拠していない


これは、次の挿入で明らかです。


SQL> insert into t2 (json_column) values (
  2  '{
  3     valid: true,
  4     someString: "some string",
  5     someNumber: 1234
  6  }'
  7* );

Error starting at line : 1 in command -
insert into t2 (json_column) values (
'{
   valid: true,
   someString: "some string",
   someNumber: 1234
}'
)
Error report -
ORA-02290: check constraint (MARTIN.C_T2_JSON) violated


入力を厳密な構文に修正した後にのみ、挿入が成功します。


SQL> insert into t2 (json_column) values (
  2  '{
  3    "valid" : true,
  4    "someString" : "some string",
  5    "someNumber" : 1234
  6  }'
  7* );

1 row inserted.

SQL> select json_column from t2 where id = 5;

JSON_COLUMN                                                                    
______________________________________________________________________________ 
{
  "valid" : true,
  "someString" : "some string",
  "someNumber" : 1234
}


Oracle Database 19cより新しいリリースはどうですか。


良いニュースは、Oracle Database 21c以降でデータベースにJSONを格納する方法について心配する必要がないことです。新しいJSONデータ型とJSONコンストラクタのおかげで、素晴らしい場所にいるはずです。


表DDLは大幅に簡略化されています。


create table t3 (
  id number generated by default on null as identity
    constraint pk_t3 primary key,
    json_column JSON
);


JSON固有のチェック制約は必要ありません(ただし、他のチェック制約が必要になる場合があります)。lax構文を使用してデータを挿入することもできます...


insert into t3 (json_column) values (
'{
   valid: true,
   someString: "some string",
   someNumber: 1234
}'
);


...ただし、問合せを行うと、厳密な構文JSONが返されることがわかります。JSON%関数を明示的に指定しない場合でも、次のようになります。


SQL> select json_column from t3;

JSON_COLUMN                                                    
______________________________________________________________ 
{"valid":true,"someString":"some string","someNumber":1234}


関数を使用する場合、OracleがJSONを返す方法に変更はありません。


SQL> select json_serialize(json_column pretty) as pretty_json from t3;

PRETTY_JSON                                                                    
______________________________________________________________________________ 
{
  "valid" : true,
  "someString" : "some string",
  "someNumber" : 1234
}


無効なJSONを格納できません:


SQL> insert into t3 (json_column) values ('this will not work');

Error starting at line : 1 in command -
insert into t3 (json_column) values ('this will not work')
Error at Command Line : 1 Column : 13
Error report -
SQL Error: ORA-40441: JSON syntax error
JZN-00078: Invalid JSON keyword 'this' (line 1, position 1)


必要に応じて、JSONコンストラクタを使用してデータを挿入できます。


SQL> insert into t3 (json_column) values ( json('{ valid: true, someNumber: 3, anotherNumber: "4" }'));

1 row inserted.

SQL> select * from t3 where id = 5;

   ID JSON_COLUMN                                          
_____ ____________________________________________________ 
    5 {"valid":true,"someNumber":3,"anotherNumber":"4"}

よく見ると、anotherNumberが文字列として挿入されていることがわかります。これは、次の記事のティーザーとして機能し、タイプ変換に対処します。



まとめ


Oracle Database 21cまでのリリースには、厳密な構文ルールに準拠した有効なJSONを強制するための追加ステップがいくつか必要でした。Oracle Database 21c以降は、ネイティブJSONデータ型を提供します。これは、すぐに使用できる多くの利点を提供するため、使用する必要があります。JSONデータ型の使用方法とは別に、ボンネットの下には目に見えない利点がたくさんあります。詳細は、JSON開発者ガイドを参照してください。


Oracle Database 23aiをまだ使用していない場合は、JSONデータのテキスト表現を使用する必要があります。その場合、is jsonチェック制約が必要であることがほぼ保証されます。アプリケーションによっては、厳密なJSONの要件も考慮する必要があります。Oracle Database 23aiへの移行プロジェクトが開始される日。テキストJSON表現からネイティブJSONデータ型への切替えを検討してください。簡単ですし、支払いが済みます。



コメント

このブログの人気の投稿

Oracle Database 19cサポート・タイムラインの重要な更新 (2024/11/20)

Oracle GoldenGate 23aiでMicrosoft Fabricでのオープン・ミラーリングがサポートされるようになりました (2024/11/19)

Oracle APEXのInteractive Gridで、Oracle Formsと比較して、重複行の検証を制御/通過させる方法 (2022/07/21)