OpenX JSON SerDe - Amazon Athena

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

OpenX JSON SerDe

像蜂房一樣 JSON SerDe,您可以使用 OpenX JSON 來處理JSON數據。數據也表示為由新行分隔的JSON編碼文本的單行字符串。像蜂巢一樣 JSON SerDe,OpenX JSON SerDe 不允許重複鍵mapstruct密鑰名稱。

考量與限制

  • 使用 OpenX 時 JSON SerDe,結果數目及其值可能是不具決定性的。結果可能包含比預期更多的資料列、比預期的列數少,或者當基礎資料中沒有任何資料時,結果可能會包含非預期的 null 值。若要解決這個問題,請使用蜂巢 JSON SerDe,或將資料重新寫入其他檔案格式類型。

  • SerDe 預期每個JSON文件都位於單行文字上,記錄中的欄位之間沒有行終止字元。如果JSON文本是漂亮的打印格式,你可能會收到一個錯誤消息,如 HIVECURSOR_ _ERROR: 行不是一個有效的JSON對象HIVECURSOR_ _ ERROR JsonParseException end-of-input: 意外:OBJECT當你嘗試查詢表後,你創建它的預期關閉標記

    如需詳細資訊,請參閱上 GitHub的 OpenX SerDe 文件中的資JSON料檔案。

可選屬性

與蜂巢不同 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")

如果您有兩個在小寫時相同的索引鍵,如 UrlURL,則可能會發生類似以下的錯誤:

HIVE_ CURSOR _ERROR:行不是一個有效的JSON對象-JSONException:重複鍵「url」

若要解決這個問題,請將 case.insensitive 屬性設定為 FALSE,並將索引鍵對應至不同的名稱,如下列範例所示:

ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.url1" = "URL", "mapping.url2" = "Url")
對應

選用。將欄名稱對應至與欄名稱不相同的JSON索引鍵。當JSON資料包含鍵字的索引鍵時,此mapping參數非常有用。例如,如果您有名為的JSON金鑰timestamp,請使用下列語法將索引鍵對應至名為的資料行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,根據 Hive JSON SerDe 範例中使用的相同範例線上廣告資料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 SerDes 來剖析更複雜的JSON編碼資料。這需要使用 CREATE TABLE 陳述式,它會使用 structarray 元素來表示巢狀結構。

下列範例會根據具有巢狀結構的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錄都位於單行文本上。存放在 Amazon S3 時,上述範例中的所有資料都應放在單行上,如下所示:

{"DocId":"AWS","User":{"Id":1234,"Username":"carlos_salazar","Name":"Carlos","ShippingAddress" ...

下列CREATE TABLE陳述式會使用 Openx-JsonSerDe 搭配structarray集合資料類型,為範例資料建立物件群組。

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 City 項目識別碼 訂單日期
1 Carlos 123 主要聖彼得堡 任何城鎮 6789 11/11/2022
2 Carlos 123 主要聖彼得堡 任何城鎮 4352 12/12/2022