

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

# 讀取 JSON 資料的最佳實務
<a name="parsing-json-data"></a>

JavaScript 物件標記法 (JSON) 是將資料結構編碼為文字的常見方法。許多應用程式和工具輸出的資料都是 JSON 編碼。

在 Amazon Athena 中，您可以從外部資料建立資料表，並將 JSON 編碼的資料加入資料表。對於此類型的來源資料，請將 Athena 搭配 [JSON SerDe 程式庫](json-serde.md) 一起使用。

使用以下秘訣讀取 JSON 編碼的資料：
+ 選擇正確的 SerDe、原生 JSON SerDe、`org.apache.hive.hcatalog.data.JsonSerDe` 或 OpenX SerDe、`org.openx.data.jsonserde.JsonSerDe`。如需詳細資訊，請參閱[JSON SerDe 程式庫](json-serde.md)。
+ 確保每一筆 JSON 編碼記錄都自成一行，並沒有呈現漂亮列印的狀態。
**注意**  
SerDe 預期每筆 JSON 文件都以單行文字表示，而且沒有行終止字元分隔記錄中的欄位。如果 JSON 文字是美化過的列印格式，則在建立資料表後嘗試在其中查詢時可能會收到下列錯誤訊息：HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object (HIVE\$1CURSOR\$1ERROR：資料列不是有效的 JSON 物件) 或 HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT (HIVE\$1CURSOR\$1ERROR：JsonParseException：非預期的輸入結束：預期為 OBJECT 的關閉標記)。如需詳細資訊，請參閱 GitHub 上 OpenX SerDe 文件中的 [JSON 資料檔案](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)。
+ 在區分大小寫的欄中產生 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://amzn-s3-demo-bucket/path/';
  ```
+ 在 Athena 中，將來源資料中結構描述不明的欄位，轉換為 JSON 編碼字串。

Athena 在建立受 JSON 資料支援的資料表時，會根據現有和預先定義的結構描述來剖析資料。不過，並非所有資料都有預先定義的結構描述。在這種情況下，為了簡化結構描述管理，通常建議在 Athena 中將來源資料中結構描述不明的欄位，轉換為 JSON 字串，然後使用 [JSON SerDe 程式庫](json-serde.md)。

例如，假設 IoT 應用程式從不同的感應器發佈含有常見欄位的事件。其中一個欄位必須存放傳送事件的感應器所獨有的自訂承載。在這種情況下，因為您不知道結構描述，建議您以 JSON 編碼字串來存放資訊。若要這樣做，請將 Athena 資料表中的資料轉換為 JSON，如下列範例所示。您也可以將 JSON 編碼的資料轉換為 Athena 資料類型。

**Topics**
+ [將 Athena 資料類型轉換為 JSON](converting-native-data-types-to-json.md)
+ [將 JSON 轉換為 Athena 資料類型](converting-json-to-native-data-types.md)

# 將 Athena 資料類型轉換為 JSON
<a name="converting-native-data-types-to-json"></a>

若要將 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 資料類型
<a name="converting-json-to-native-data-types"></a>

若要將 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} |
+-------------------------------------+
```