メインコンテンツまでスキップ
バージョン: 26.x

JSONへの/からのキャスト

DorisのJSON型は、テキスト保存ではなくバイナリエンコーディングを使用して格納され、より効率的な処理と保存を提供します。JSON型とDoris内部型の間には一対一のマッピングがあります。

JSONへのキャスト

StringからJSONへ

文字列をJSONにキャストする場合、文字列の内容はRFC7159で定義された有効なJSON構文に準拠している必要があります。パーサーは文字列を検証し、対応するJSONバイナリ形式に変換します。

文字列解析ルール

  • 文字列が有効なJSON構造(オブジェクト、配列、数値、真偽値、またはnull)を含む場合、そのJSON型として解析されます:

    mysql> SELECT CAST('[1,2,3,4]' AS JSON); -- Output: [1,2,3,4] (parsed as JSON array)
    +---------------------------+
    | CAST('[1,2,3,4]' AS JSON) |
    +---------------------------+
    | [1,2,3,4] |
    +---------------------------+
  • JSON文字列値を作成するには(文字列自体が解析されるのではなく、JSON文字列値として扱われる場合)、TO_JSON関数を使用します:

    mysql> SELECT TO_JSON('[1,2,3,4]'); -- Output: "[1,2,3,4]" (a JSON string with quotes)
    +----------------------+
    | TO_JSON('[1,2,3,4]') |
    +----------------------+
    | "[1,2,3,4]" |
    +----------------------+

Numeric Parsing Rules

JSON文字列から数値を解析する際:

  • 数値に小数点が含まれている場合、JSON Double型に変換されます:

    mysql> SELECT JSON_TYPE(CAST('{"key":123.45}' AS JSON), '$.key');
    +------------------------------------------------------+
    | JSON_TYPE(CAST('{"key":123.45}' AS JSON), '$.key') |
    +------------------------------------------------------+
    | double |
    +------------------------------------------------------+
  • 数値が整数の場合、最小の互換性のある整数型として格納されます:

    mysql> SELECT JSON_TYPE(CAST('{"key":123456789}' AS JSON), '$.key');
    +---------------------------------------------------------+
    | JSON_TYPE(CAST('{"key":123456789}' AS JSON), '$.key') |
    +---------------------------------------------------------+
    | int |
    +---------------------------------------------------------+
    mysql> SELECT JSON_TYPE(CAST('{"key":1234567891234}' AS JSON), '$.key');
    +-------------------------------------------------------------+
    | JSON_TYPE(CAST('{"key":1234567891234}' AS JSON), '$.key') |
    +-------------------------------------------------------------+
    | bigint |
    +-------------------------------------------------------------+
  • 整数がInt128の範囲を超える場合、doubleとして格納され、精度の損失が生じる可能性があります:

    mysql> SELECT JSON_TYPE(CAST('{"key":12345678901234567890123456789012345678901234567890}' AS JSON), '$.key');
    +--------------------------------------------------------------------------------------------------+
    | JSON_TYPE(CAST('{"key":12345678901234567890123456789012345678901234567890}' AS JSON), '$.key') |
    +--------------------------------------------------------------------------------------------------+
    | double |
    +--------------------------------------------------------------------------------------------------+

エラーハンドリング

文字列をJSONにパースする場合:

  • strict mode(デフォルト)では、無効なJSON構文によりエラーが発生します
  • non-strict modeでは、無効なJSON構文はNULLを返します
mysql> SET enable_strict_cast = false;
mysql> SELECT CAST('{"invalid JSON' AS JSON);
+-----------------------------+
| CAST('{"invalid JSON' AS JSON) |
+-----------------------------+
| NULL |
+-----------------------------+

mysql> SET enable_strict_cast = true;
mysql> SELECT CAST('{"invalid JSON' AS JSON);
ERROR 1105 (HY000): errCode = 2, detailMessage = (127.0.0.1)[INVALID_ARGUMENT]Failed to parse json string: {"invalid JSON, ...

FROM Other Doris Types

以下のDorisタイプは、精度を失うことなく直接JSONにキャストできます:

Doris タイプJSON タイプ
BOOLEANBool
TINYINTInt8
SMALLINTInt16
INTInt32
BIGINTInt64
LARGEINTInt128
FLOATFloat
DOUBLEDouble
DECIMALDecimal
STRINGString
ARRAYArray
STRUCTObject

-- Integer array to JSON
mysql> SELECT CAST(ARRAY(123,456,789) AS JSON);
+----------------------------------+
| CAST(ARRAY(123,456,789) AS JSON) |
+----------------------------------+
| [123,456,789] |
+----------------------------------+

-- Decimal array to JSON (preserves precision)
mysql> SELECT CAST(ARRAY(12345678.12345678,0.00000001,12.000000000000000001) AS JSON);
+--------------------------------------------------------------------------+
| CAST(ARRAY(12345678.12345678,0.00000001,12.000000000000000001) AS JSON) |
+--------------------------------------------------------------------------+
| [12345678.123456780000000000,0.000000010000000000,12.000000000000000001] |
+--------------------------------------------------------------------------+

直接サポートされていない型

上記の表にない型は、JSONに直接キャストできません:

mysql> SELECT CAST(MAKEDATE(2021, 1) AS JSON);
ERROR 1105 (HY000): CAST AS JSONB can only be performed between JSONB, String, Number, Boolean, Array, Struct types. Got Date to JSONB

解決方法:まず互換性のある型にキャストし、次にJSONにキャストします:

mysql> SELECT CAST(CAST(MAKEDATE(2021, 1) AS BIGINT) AS JSON);
+---------------------------------------------------+
| CAST(CAST(MAKEDATE(2021, 1) AS BIGINT) AS JSON) |
+---------------------------------------------------+
| 20210101 |
+---------------------------------------------------+

JSONからのキャスト

動作の変更

バージョン4.0より前では、DorisはJSON CASTの動作に対してより緩い要件を持っており、オーバーフロー状況を適切に処理していませんでした。

バージョン4.0以降、JSON CASTでのオーバーフローは、strictモードではエラーが発生し、non-strictモードではnullが返されます。

BOOLEANへの変換

JSON Bool、Number、およびString型はBOOLEANにキャストできます:

-- From JSON Bool
mysql> SELECT CAST(CAST('true' AS JSON) AS BOOLEAN);
+---------------------------------------+
| CAST(CAST('true' AS JSON) AS BOOLEAN) |
+---------------------------------------+
| 1 |
+---------------------------------------+

-- From JSON Number
mysql> SELECT CAST(CAST('123' AS JSON) AS BOOLEAN);
+--------------------------------------+
| CAST(CAST('123' AS JSON) AS BOOLEAN) |
+--------------------------------------+
| 1 |
+--------------------------------------+

-- From JSON String (must contain valid boolean representation)
mysql> SELECT CAST(TO_JSON('true') AS BOOLEAN);
+----------------------------------+
| CAST(TO_JSON('true') AS BOOLEAN) |
+----------------------------------+
| 1 |
+----------------------------------+

TO Numeric Types

JSON Bool、Number、String型は数値型(TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、DECIMAL)にキャストできます:

-- From JSON Number to INT
mysql> SELECT CAST(CAST('123' AS JSON) AS INT);
+----------------------------------+
| CAST(CAST('123' AS JSON) AS INT) |
+----------------------------------+
| 123 |
+----------------------------------+

-- From JSON Bool to numeric types
mysql> SELECT CAST(CAST('true' AS JSON) AS INT), CAST(CAST('false' AS JSON) AS DOUBLE);
+-----------------------------------+--------------------------------------+
| CAST(CAST('true' AS JSON) AS INT) | CAST(CAST('false' AS JSON) AS DOUBLE) |
+-----------------------------------+--------------------------------------+
| 1 | 0 |
+-----------------------------------+--------------------------------------+

より小さな型にキャストする際は、数値オーバーフロー規則が適用されます:

-- In strict mode, overflow causes error
mysql> SET enable_strict_cast = true;
mysql> SELECT CAST(TO_JSON(12312312312312311) AS INT);
ERROR 1105 (HY000): Cannot cast from jsonb value type 12312312312312311 to doris type INT

-- In non-strict mode, overflow returns NULL
mysql> SET enable_strict_cast = false;
mysql> SELECT CAST(TO_JSON(12312312312312311) AS INT);
+-----------------------------------------+
| CAST(TO_JSON(12312312312312311) AS INT) |
+-----------------------------------------+
| NULL |
+-----------------------------------------+

TO String

任意のJSON型はSTRINGにキャストすることができ、これによりJSONテキスト表現が生成されます:

mysql> SELECT CAST(CAST('{"key1":"value1","key2":123}' AS JSON) AS STRING);
+----------------------------------------------------------+
| CAST(CAST('{"key1":"value1","key2":123}' AS JSON) AS STRING) |
+----------------------------------------------------------+
| {"key1":"value1","key2":123} |
+----------------------------------------------------------+

mysql> SELECT CAST(CAST('true' AS JSON) AS STRING);
+--------------------------------------+
| CAST(CAST('true' AS JSON) AS STRING) |
+--------------------------------------+
| true |
+--------------------------------------+

TO Array

JSON ArrayとStringタイプは、DorisのARRAYタイプにキャストできます:

mysql> SELECT CAST(TO_JSON(ARRAY(1,2,3)) AS ARRAY<INT>);
+-------------------------------------------+
| CAST(TO_JSON(ARRAY(1,2,3)) AS ARRAY<INT>) |
+-------------------------------------------+
| [1, 2, 3] |
+-------------------------------------------+

-- タイプ conversion within array elements
mysql> SELECT CAST(TO_JSON(ARRAY(1.2,2.3,3.4)) AS ARRAY<INT>);
+-------------------------------------------------+
| CAST(TO_JSON(ARRAY(1.2,2.3,3.4)) AS ARRAY<INT>) |
+-------------------------------------------------+
| [1, 2, 3] |
+-------------------------------------------------+

-- Convert string to array
mysql> SELECT CAST(TO_JSON("['123','456']") AS ARRAY<INT>);
+----------------------------------------------+
| CAST(TO_JSON("['123','456']") AS ARRAY<INT>) |
+----------------------------------------------+
| [123, 456] |
+----------------------------------------------+

配列内の要素は、標準のキャスト規則に従って個別に変換されます:

-- In non-strict mode, invalid elements become NULL
mysql> SET enable_strict_cast = false;
mysql> SELECT CAST(TO_JSON(ARRAY(10,20,200)) AS ARRAY<TINYINT>);
+---------------------------------------------------+
| CAST(TO_JSON(ARRAY(10,20,200)) AS ARRAY<TINYINT>) |
+---------------------------------------------------+
| [10, 20, null] |
+---------------------------------------------------+

-- In strict mode, invalid elements cause error
mysql> SET enable_strict_cast = true;
mysql> SELECT CAST(TO_JSON(ARRAY(10,20,200)) AS ARRAY<TINYINT>);
ERROR 1105 (HY000): Cannot cast from jsonb value type 200 to doris type TINYINT

TO Struct

JSON ObjectとString型は、DorisのSTRUCT型にキャストできます:

mysql> SELECT CAST(CAST('{"key1":123,"key2":"456"}' AS JSON) AS STRUCT<key1:INT,key2:STRING>);
+------------------------------------------------------------------------------+
| CAST(CAST('{"key1":123,"key2":"456"}' AS JSON) AS STRUCT<key1:INT,key2:STRING>) |
+------------------------------------------------------------------------------+
| {"key1":123, "key2":"456"} |
+------------------------------------------------------------------------------+

mysql> SELECT CAST(TO_JSON('{"key1":123,"key2":"456"}') AS STRUCT<key1:INT,key2:STRING>);
+----------------------------------------------------------------------------+
| CAST(TO_JSON('{"key1":123,"key2":"456"}') AS STRUCT<key1:INT,key2:STRING>) |
+----------------------------------------------------------------------------+
| {"key1":123, "key2":"456"} |
+----------------------------------------------------------------------------+

構造体内のフィールドは、指定された型に従って個別に変換されます:

mysql> SELECT CAST(CAST('{"key1":[123.45,678.90],"key2":[12312313]}' AS JSON) AS STRUCT<key1:ARRAY<DOUBLE>,key2:ARRAY<BIGINT>>);
+--------------------------------------------------------------------------------------------------------------------------+
| CAST(CAST('{"key1":[123.45,678.90],"key2":[12312313]}' AS JSON) AS STRUCT<key1:ARRAY<DOUBLE>,key2:ARRAY<BIGINT>>) |
+--------------------------------------------------------------------------------------------------------------------------+
| {"key1":[123.45, 678.9], "key2":[12312313]} |
+--------------------------------------------------------------------------------------------------------------------------+

JSONと構造体定義の間で、フィールド数と名前が一致している必要があります:

-- In non-strict mode, mismatched fields return NULL
mysql> SET enable_strict_cast = false;
mysql> SELECT CAST(CAST('{"key1":123,"key2":456}' AS JSON) AS STRUCT<key1:INT>);
+-------------------------------------------------------------------------+
| CAST(CAST('{"key1":123,"key2":456}' AS JSON) AS STRUCT<key1:INT>) |
+-------------------------------------------------------------------------+
| NULL |
+-------------------------------------------------------------------------+

-- In strict mode, mismatched fields cause error
mysql> SET enable_strict_cast = true;
mysql> SELECT CAST(CAST('{"key1":123,"key2":456}' AS JSON) AS STRUCT<key1:INT>);
ERROR 1105 (HY000): jsonb_value field size 2 is not equal to struct size 1

JSON Null処理

JSON nullはSQL NULLとは異なります:

  • JSONフィールドがnull値を含む場合、それを任意のDoris型にキャストするとSQL NULLが生成されます:
mysql> SELECT CAST(CAST('null' AS JSON) AS INT);
+----------------------------------+
| CAST(CAST('null' AS JSON) AS INT) |
+----------------------------------+
| NULL |
+----------------------------------+

型変換の概要

JSONタイプキャスト可能な型
BoolBOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DOUBLE, FLOAT, DECIMAL, STRING
Null(常にSQL NULLに変換される)
NumberBOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DOUBLE, FLOAT, DECIMAL, STRING
StringBOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DOUBLE, FLOAT, DECIMAL, STRING, ARRAY, STRUCT
ArraySTRING, ARRAY
ObjectSTRING, STRUCT

キーワード

JSON, JSONB, CAST, conversion, to_json