本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
OpenX JSON SerDe
像蜂房一樣 JSON SerDe,您可以使用 OpenX JSON 來處理JSON數據。數據也表示為由新行分隔的JSON編碼文本的單行字符串。像蜂巢一樣 JSON SerDe,OpenX JSON SerDe 不允許重複鍵map
或struct
密鑰名稱。
考量與限制
-
使用 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")
如果您有兩個在小寫時相同的索引鍵,如
Url
和URL
,則可能會發生類似以下的錯誤: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
陳述式,它會使用 struct
和 array
元素來表示巢狀結構。
下列範例會根據具有巢狀結構的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-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 | City | 項目識別碼 | 訂單日期 |
---|---|---|---|---|---|
1 | Carlos | 123 主要聖彼得堡 | 任何城鎮 | 6789 | 11/11/2022 |
2 | Carlos | 123 主要聖彼得堡 | 任何城鎮 | 4352 | 12/12/2022 |