OpenX JSON SerDe
Hive JSON SerDe と同様に、OpenX JSON を使用して JSON データを処理できます。また、データは改行で区切られ JSON 形式でエンコードされたテキストの 1 行の文字列としても表現されます。Hive JSON SerDe と同様に、OpenX JSON SerDe では、map
または struct
キー名の重複キーは許可されません。
考慮事項と制限事項
-
OpenX JSON SerDe を使用する場合、結果の数とその値は非決定的である可能性があります。結果に含まれる行数が予想よりも多かったり少なかったりする可能性があり、基になるデータに何も存在しない場合に予期しない null 値が含まれる可能性もあります。この問題を回避するには、Hive JSON SerDe を使用するか、データを別のファイル形式タイプに書き換えます。
-
SerDe では、各 JSON ドキュメントが、レコード内のフィールドを区切る行終端文字なしの、1 行のテキストに収まっていることを想定しています。JSON テキストがプリティプリント形式の場合、テーブルを作成した後にクエリを実行しようとすると、以下のようなエラーメッセージが表示される場合があります。「
HIVE_CURSOR_ERROR: Row is not a valid JSON Object
」、または「HIVE_CURSOR_ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT
」。詳細については、GitHub の OpenX SerDe のドキュメントで「JSON Data Files
」(JSON データファイル) を参照してください。
オプションのプロパティ
Hive JSON SerDe とは異なり、OpenX JSON SerDe には、データの不整合に対処するのに役立つ次のオプションの SerDe プロパティもあります。
- ignore.malformed.json
-
オプション。
TRUE
に設定すると、不正な形式の JSON 構文を無視できます。デフォルト:FALSE
。 - dots.in.keys
-
オプション。デフォルト:
FALSE
。TRUE
に設定すると、SerDe はキー名のドットをアンダースコアに置き換えることができます。例えば、JSON データセットに"a.b"
という名前のキーが含まれている場合は、このプロパティを使用して、Athena で列名が"a_b"
になるように定義できます。デフォルトで (この SerDe がない場合)、Athena は列名にドットを許可しません。 - case.insensitive
-
オプション。デフォルト:
TRUE
。TRUE
に設定すると、SerDe はすべての大文字の列を小文字に変換します。データで大文字と小文字を区別するキー名を使用するには、
WITH SERDEPROPERTIES ("case.insensitive"= FALSE;)
を使用します。次に、まだすべてが小文字になっていないすべてのキーに、次の構文を使用して列名からプロパティ名へのマッピングを指定します。ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.userid" = "userId")
URL
とUrl
のように小文字である 2 つのキーがある場合は、次のようなエラーが発生する可能性があります。HIVE_CURSOR_ERROR: Row is not a valid JSON Object - JSONException: Duplicate key "url"
これを解決するには、次の例のように、
case.insensitive
プロパティをFALSE
に設定し、キーを異なる名前にマッピングします。ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.url1" = "URL", "mapping.url2" = "Url")
- マッピングを
-
オプション。列名を、列名と同一ではない JSON キーにマップします。
mapping
パラメータは、JSON データにキーワードのキーが含まれている場合に便利です。たとえば、timestamp
という名前の JSON キーがある場合、次の構文を使用して、キーをts
という名前の列にマッピングします。ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("mapping.ts" = "timestamp")
コロンを含むネストされたフィールド名を Hive 互換の名前にマッピングする
struct
の内部にコロンを含むフィールド名がある場合は、mapping
プロパティを使用してそのフィールドを Hive 互換の名前にマップできます。例えば、列タイプの定義にmy:struct:field:string
を含めることで、WITH SERDEPROPERTIES
で次のエントリー定義をmy_struct_field:string
にマップできます。("mapping.my_struct_field" = "my:struct:field")
次の例は、対応する
CREATE TABLE
ステートメントを示しています。CREATE EXTERNAL TABLE colon_nested_field ( item struct<my_struct_field:string>) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("mapping.my_struct_field" = "my:struct:field")
例: 広告データ
次の DDL ステートメントの例では、OpenX JSON SerDe を使用して、Hive JSON SerDe の例で使用したのと同じサンプルオンライン広告データに基づいてテーブルを作成します。LOCATION
句で、myregion
を Athena が実行されるリージョンの識別子に置き換えます。
CREATE EXTERNAL TABLE impressions ( requestbegintime string, adid string, impressionId string, referrer string, useragent string, usercookie string, ip string, number string, processid string, browsercokie string, requestendtime string, timers struct< modellookup:string, requesttime:string>, threadid string, hostname string, sessionid string ) PARTITIONED BY (dt string) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION 's3://amzn-s3-demo-bucket.elasticmapreduce/samples/hive-ads/tables/impressions';
例: ネスト JSON の逆シリアル化
JSON SerDe を使用して、より複雑な JSON エンコードされたデータを解析できます。このためには、ネストされた構造を表すために struct
要素と array
要素を使用する CREATE TABLE
ステートメントを使用する必要があります。
以下の例は、ネストされた構造を持つ JSON データから Athena テーブルを作成します。サンプルは次の構造になっています。
{
"DocId": "AWS",
"User": {
"Id": 1234,
"Username": "carlos_salazar",
"Name": "Carlos",
"ShippingAddress": {
"Address1": "123 Main St.",
"Address2": null,
"City": "Anytown",
"State": "CA"
},
"Orders": [
{
"ItemId": 6789,
"OrderDate": "11/11/2022"
},
{
"ItemId": 4352,
"OrderDate": "12/12/2022"
}
]
}
}
OpenX SerDe は、各 JSON レコードが 1 行のテキスト上にあることを期待することに注意してください。Amazon S3 に保存されている場合、前の例のすべてのデータを、次に示すように 1 行で表記する必要があります。
{"DocId":"AWS","User":{"Id":1234,"Username":"carlos_salazar","Name":"Carlos","ShippingAddress" ...
次の CREATE TABLE
ステートメントは、Openx-JsonSerDestruct
および array
コレクションデータ型とともに使用して、サンプルデータ用にオブジェクトのグループを構築します。
CREATE external TABLE complex_json ( docid string, `user` struct< id:INT, username:string, name:string, shippingaddress:struct< address1:string, address2:string, city:string, state:string >, orders:array< struct< itemid:INT, orderdate:string > > > ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION 's3://amzn-s3-demo-bucket/
myjsondata
/';
テーブルをクエリするには、次のような SELECT
ステートメントを使用します。
SELECT user.name as Name, user.shippingaddress.address1 as Address, user.shippingaddress.city as City, o.itemid as Item_ID, o.orderdate as Order_date FROM complex_json, UNNEST(user.orders) as temp_table (o)
構造体内のデータフィールドにアクセスするために、サンプルクエリはドット表記 (user.name
など) を使用します。(orders
フィールドと同様に) 構造体の配列内のデータにアクセスするには、UNNEST
関数を使用できます。UNNEST
関数は配列を一時テーブル (この場合は o
) にフラット化します。これにより、構造体と同様にドット表記を使用して、ネストされていない配列要素 (o.itemid
など) にアクセスできます。この例で説明のために使用されている名前 temp_table
は、多くの場合、t
と省略されます。
次の表にクエリ結果を示します。
# | 名前 | Address | 市町村 | Item_ID | Order_date |
---|---|---|---|---|---|
1 | Carlos | 123 Main St. | Anytown | 6789 | 11/11/2022 |
2 | Carlos | 123 Main St. | Anytown | 4352 | 12/12/2022 |