本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
讀取 JSON 資料的最佳實務
JavaScript 對象符號(JSON)是將數據結構編碼為文本的常用方法。許多應用程式和工具輸出的資料都是 JSON 編碼。
在 Amazon Athena 中,您可以從外部資料建立資料表,並將 JSON 編碼的資料加入資料表。對於此類型的來源資料,請將 Athena 搭配 JSON SerDe 程式庫 一起使用。
使用以下秘訣讀取 JSON 編碼的資料:
-
選擇正確的 SerDe、原生 JSON SerDe 或 OpenX SerDe、
org.openx.data.jsonserde.JsonSerDe
。org.apache.hive.hcatalog.data.JsonSerDe
如需詳細資訊,請參閱 JSON SerDe 程式庫。 -
確保每一筆 JSON 編碼記錄都自成一行,並沒有呈現漂亮列印的狀態。
注意
SerDe 預期每個 JSON 文件都位於單行文字上,且記錄中欄位之間沒有行終止字元。如果 JSON 文本是漂亮的打印格式,您可能會收到一條錯誤消息,如
HIVE_CURSOR_ERROR:行不是有效的 JSON 對象
或HIVE_CURSOR_ERROR:: 意外 JsonParseException end-of-input:當您嘗試查詢表後創建表時,對象的預期關閉標記
。如需詳細資訊,請參閱上 GitHub的 OpenX SerDe 文件中的 JSON 資料檔案。 -
在區分大小寫的欄中產生 JSON 編碼的資料。
-
提供選項以忽略格式不正確的記錄,如這個範例所示。
CREATE EXTERNAL TABLE json_table ( column_a string, column_b int ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ('ignore.malformed.json' = 'true')
LOCATION 's3://DOC-EXAMPLE-BUCKET/path/'; -
在 Athena 中,將來源資料中結構描述不明的欄位,轉換為 JSON 編碼字串。
Athena 在建立受 JSON 資料支援的資料表時,會根據現有和預先定義的結構描述來剖析資料。不過,並非所有資料都有預先定義的結構描述。在這種情況下,為了簡化結構描述管理,通常建議在 Athena 中將來源資料中結構描述不明的欄位,轉換為 JSON 字串,然後使用 JSON SerDe 程式庫。
例如,假設 IoT 應用程式從不同的感應器發佈含有常見欄位的事件。其中一個欄位必須存放傳送事件的感應器所獨有的自訂承載。在這種情況下,因為您不知道結構描述,建議您以 JSON 編碼字串來存放資訊。若要這樣做,請將 Athena 資料表中的資料轉換為 JSON,如下列範例所示。您也可以將 JSON 編碼的資料轉換為 Athena 資料類型。
將 Athena 資料類型轉換為 JSON
若要將 Athena 資料類型轉換為 JSON,請使用 CAST
。
WITH dataset AS ( SELECT CAST('HELLO ATHENA' AS JSON) AS hello_msg, CAST(12345 AS JSON) AS some_int, CAST(MAP(ARRAY['a', 'b'], ARRAY[1,2]) AS JSON) AS some_map ) SELECT * FROM dataset
此查詢會傳回:
+-------------------------------------------+
| hello_msg | some_int | some_map |
+-------------------------------------------+
| "HELLO ATHENA" | 12345 | {"a":1,"b":2} |
+-------------------------------------------+
將 JSON 轉換為 Athena 資料類型
若要將 JSON 資料轉換為 Athena 資料類型,請使用 CAST
。
注意
在這個範例中,若要以 JSON 編碼表示字串,請以 JSON
關鍵字為開頭,並使用單引號,例如 JSON
'12345'
WITH dataset AS ( SELECT CAST(JSON '"HELLO ATHENA"' AS VARCHAR) AS hello_msg, CAST(JSON '12345' AS INTEGER) AS some_int, CAST(JSON '{"a":1,"b":2}' AS MAP(VARCHAR, INTEGER)) AS some_map ) SELECT * FROM dataset
此查詢會傳回:
+-------------------------------------+
| hello_msg | some_int | some_map |
+-------------------------------------+
| HELLO ATHENA | 12345 | {a:1,b:2} |
+-------------------------------------+