JSON SerDe 库 - Amazon Athena
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

JSON SerDe 库

在 Athena 中,您可以使用两个 SerDe 库来处理以 JSON 格式的文件:

SerDe 名称

Hive-JsonSerDe

Openx-JsonSerDe

库名称

使用以下值之一:

org.apache.hive.hcatalog.data.JsonSerDe

org.openx.data.jsonserde.JsonSerDe

Hive JSON SerDe

Hive JSON SerDe 用于处理 JSON 数据,最常见的是事件。这些事件表示为由换行符分隔的 JSON 编码文本块。

您还可以使用 Hive JSON SerDe 来解析具有嵌套结构的更复杂的 JSON 编码的数据。但是,这需要具有一个表示复杂数据类型的匹配 DDL。请参阅示例:反序列化嵌套 JSON.

使用此 SerDe 时,map(或 struct)键名称中不允许重复的键。

以下 DDL 语句使用 Hive JSON SerDe:

CREATE EXTERNAL TABLE impressions ( requestbegintime string, adid string, impressionid string, referrer string, useragent string, usercookie string, ip string, number string, processid string, browsercookie string, requestendtime string, timers struct < modellookup:string, requesttime:string >, threadid string, hostname string, sessionid string ) PARTITIONED BY (dt string) ROW FORMAT serde 'org.apache.hive.hcatalog.data.JsonSerDe' with serdeproperties ( 'paths'='requestbegintime, adid, impressionid, referrer, useragent, usercookie, ip' ) LOCATION 's3://myregion.elasticmapreduce/samples/hive-ads/tables/impressions';

OpenX JSON SerDe

OpenX SerDe 由 Athena 用于反串行化数据,这表示将其从 JSON 格式转换,以准备串行化为 Parquet 或 ORC 格式。这是您可以选择的两种解串器之一,具体取决于哪一款提供了您需要的功能。另一个选项是 Hive JsonSerDe。

此 SerDe 有几个有用的属性,您可以在 Athena 中创建表时指定这些属性,以帮助解决数据中的不一致问题:

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;)。然后,对于每个非全部小写的键,请使用以下语法提供从列名到属性名的映射:

WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.userid" = "userId")

如果您有两个键(例如 URLUrl),并且二者在小写时是相同的,则可能会发生与以下内容类似的错误:

HIVE_CURSOR_ERROR: Row is not a valid JSON Object - JSONException: Duplicate key "url"(HIVE_CURSOR_ERROR:行不是有效的 JSON 对象 - JSONException:重复的键“url”)

要纠正此错误,请将 case.insensitive 属性设置为 FALSE,并将键映射到不同的名称,如以下示例所示:

WITH SERDEPROPERTIES ("case.insensitive" = "FALSE", "mapping.url1" = "URL", "mapping.url2" = "Url")
ColumnToJsonKeyMappings

可选。将列名映射到与列名不同的 JSON 键。当 JSON 数据包含作为关键字的键时,这很有用。例如,如果您有名为 timestamp 的 JSON 键,请将此参数设置为 {"ts": "timestamp"},以将此键映射到名为 ts 的列。此参数获取字符串类型的值。它使用以下键模式:^\S+$,以及以下值模式:^(?!\s*$).+

使用此 SerDe 时,map(或 struct)键名称中不允许重复的键。

以下 DDL 语句使用 OpenX JSON SerDe:

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' with serdeproperties ( 'paths'='requestbegintime, adid, impressionid, referrer, useragent, usercookie, ip' ) LOCATION 's3://myregion.elasticmapreduce/samples/hive-ads/tables/impressions';

示例:反序列化嵌套 JSON

当在 Athena 中创建表时,JSON 数据可能难以反序列化。

在处理复杂的嵌套 JSON 时,您可能遇到一些常见问题。有关这些问题和故障排除实践的更多信息,请参阅 AWS 知识中心文章当我尝试读取 Amazon Athena 中的 JSON 数据时收到错误

有关常见情况和查询提示的更多信息,请参阅使用 JSONSerDe 从嵌套 JSON 和映射在 Amazon Athena 中创建表

以下示例演示了一种简单的方法来从具有嵌套结构以 JSON 格式的数据创建 Athena 表。要在 Athena 中解析 JSON 编码的数据,每个 JSON 文档必须各占一行,并用换行符分隔。

此示例假定 JSON 编码的数据具有以下结构:

{ "DocId": "AWS", "User": { "Id": 1234, "Username": "bob1234", "Name": "Bob", "ShippingAddress": { "Address1": "123 Main St.", "Address2": null, "City": "Seattle", "State": "WA" }, "Orders": [ { "ItemId": 6789, "OrderDate": "11/11/2017" }, { "ItemId": 4352, "OrderDate": "12/12/2017" } ] } }

以下 CREATE TABLE 命令使用 Openx-JsonSerDe 与集合数据类型 (如 structarray) 来建立对象组。每个 JSON 文档都在其自己的行上列出,并用换行符分隔。为了避免错误,所查询的数据不会在 struct 和映射键名称中包含重复的键。映射(或 struct)键名称中不允许有重复的键。

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://mybucket/myjsondata/';