如何使用单个字段的混合结构/字符串值解析 Hive 中的 JSON?

Posted

技术标签:

【中文标题】如何使用单个字段的混合结构/字符串值解析 Hive 中的 JSON?【英文标题】:How to parse JSONs in Hive with Mixed Struct/String values for a single field? 【发布时间】:2020-02-20 03:06:24 【问题描述】:

我有 JSON 数据,其结构类似于:

root
 |-- TX: struct (nullable = true)
 |    |-- ARGS: array (nullable = true)
 |    |    |-- element: string (containsNull = true)
 |    |-- COOKIE: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- name: string (nullable = true)
 |    |    |    |-- value: string (nullable = true)

数据的格式实际上ARGS 数组包含结构(名称-值对,就像COOKIE 数组一样),如下所示:

ARGS: "name": "url", "value": "/index.html"

但是,在文件的某些行中,ARGS 数组仅包含一个空值,这迫使 Hive 将其解释为字符串:

ARGS: null

因为我知道ARGS 中的所有非空值都是结构,所以我在 Hive 中使用 CREATE 语句,如下所示:

CREATE EXTERNAL TABLE $db.$table(
    tx struct<
        args:array<struct<name:string,value:string>>,
        cookie:array<struct<name:string,value:string>>
    >
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION '$uri';

由于这里的最终目标是横向化键值对数组,所以我使用这样的查询来测试:

SELECT array_pairs.name, array_pairs.value 
FROM $db.$table
LATERAL VIEW EXPLODE(tx.args) EXPLODED_TABLE AS array_pairs;

如果我只查看 Hue 中的前 100 行左右,这可以正常工作。但是,如果我尝试将其导出为 CSV 或使用读取整个表的 WHERE 子句,Hive 会由于数据类型不匹配而弹出此错误:

errorMessage='java.lang.Error: Data is not JSONObject but java.lang.String with value alpha'

我知道最好的答案是拥有一个完美的数据源,但在这种情况下,数据就是它本来的样子,我必须解析它。有关如何使用 Hive 解析处理 JSON 中的空值的任何提示?

编辑 2019 年 10 月 24 日 07:43

感谢@leftjoin,我意识到除了空值之外,还有一个或两个 JSON 对象,其中 ARGS 字段由数组中的单个字符串填充:

ARGS: ["string value"]

鉴于此,Hive 解析器是否可以忽略这些字符串,从而提取键值对?

【问题讨论】:

这不是因为空值。检查文字而不是结构 该死,你是对的。我添加了新信息的编辑。 【参考方案1】:

尝试将SerDe property 设置为忽略格式错误的 JSON:

ALTER TABLE json_table SET SERDEPROPERTIES ( "ignore.malformed.json" = "true");

【讨论】:

不幸的是,一旦更改表结构,就会产生相同的查询错误。

以上是关于如何使用单个字段的混合结构/字符串值解析 Hive 中的 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

Hive 解析和编辑数组到结构字段

通过 RestKit 使用单个字符串元素列表解析 JSON

Hive -解析json(get_json_object)

从列值生成 Hive 行

hive里面怎样将数组类型的字段设置成NULL值

Google Apps 脚本 - 如何解析响应