讀取 JSON 資料的最佳實務 - Amazon Athena

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

讀取 JSON 資料的最佳實務

JavaScript 對象符號(JSON)是將數據結構編碼為文本的常用方法。許多應用程式和工具輸出的資料都是 JSON 編碼。

在 Amazon Athena 中,您可以從外部資料建立資料表,並將 JSON 編碼的資料加入資料表。對於此類型的來源資料,請將 Athena 搭配 JSON SerDe 程式庫 一起使用。

使用以下秘訣讀取 JSON 編碼的資料:

  • 選擇正確的 SerDe、原生 JSON SerDe 或 OpenX SerDe、org.openx.data.jsonserde.JsonSerDeorg.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} | +-------------------------------------+