TL;DR
- 场景:Hive 离线数仓里处理 JSON 字段,既要取数组又要展开成多行,还要兼容纯 JSON 文件入表
- 结论:嵌套/数组优先 UDF+explode;纯 JSON 文件优先 JsonSerDe;简单字段用 json_tuple / get_json_object
- 产出:可复用的 Java UDF(JSON 数组→array)+ 3 组可直接跑的 Hive SQL 模板
JSON 数据处理
使用UDF处理
自定义UDF处理JSON串中的数组,自定义UDF函数:
- 输入:JSON串、数组的Key
- 输出:字符串数组
UDF(User Defined Function)
UDF 是用户定义的函数,用于扩展大数据处理系统的功能。通过 UDF,用户可以实现特定的业务逻辑,用于数据的转换或计算。
扩展性
Hive、Spark SQL 等大数据处理工具虽然提供了丰富的内置函数,但在实际业务场景中经常会遇到内置函数无法满足的特殊需求。UDF 机制允许用户根据业务需求实现自定义逻辑,极大地扩展了数据处理能力。
灵活性
UDF 支持多种编程语言实现:Java、Python、Scala、JavaScript
主要类型
- 普通 UDF:单行输入单行输出
- UDAF:多行输入单行输出,聚合函数
- UDTF:单行输入多行输出,配合 LATERAL VIEW 使用
编写代码
导入依赖
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>2.3.7</version>
<scope>provided</scope>
</dependency>
编写代码
package icu.wzk;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.hadoop.hive.ql.exec.UDF;
import java.util.ArrayList;
public class ParseJsonArray extends UDF {
public ArrayList<String> evaluate(String jsonStr, String arrKey) {
if (jsonStr == null || jsonStr.isEmpty()) {
return null;
}
try {
JSONObject object = JSON.parseObject(jsonStr);
JSONArray jsonArray = object.getJSONArray(arrKey);
ArrayList<String> result = new ArrayList<>();
for (Object o : jsonArray) {
result.add(o.toString());
}
return result;
} catch (Exception e) {
return null;
}
}
}
测试函数
-- 添加自定义的jar包
add jar /opt/wzk/hive-parse-json-array-1.0-SNAPSHOT-jar-with-dependencies.jar;
-- 创建临时函数
CREATE temporary function wzk_json_array AS "icu.wzk.ParseJsonArray";
-- 执行查询测试
SELECT username, age, sex, wzk_json_array(json, "ids") ids FROM jsont1;
-- 解析json串中的数组,并展开
SELECT username, age, sex, ids1
FROM jsont1
lateral view explode(wzk_json_array(json, "ids")) t1 AS ids1;
使用SerDe处理
SerDe(Serializer and Deserializer)
SerDe 是序列化与反序列化的缩写,用于定义数据的读写方式。
SerDe 的作用
- 反序列化:将存储中的字节流解析成 Hive 表中的行数据
- 序列化:将 Hive 表中的行数据转换为存储格式
- 支持自定义数据格式
创建数据
{"id": 1,"ids": [101,102,103],"total_number": 3}
{"id": 2,"ids": [201,202,203,204],"total_number": 4}
进行测试
CREATE TABLE jsont2(
id int,
ids array<string>,
total_number int
) ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe';
load data local inpath '/opt/wzk/json2.dat' into table jsont2;
最后小结
- 简单格式的JSON数据,使用 get_json_object、json_tuple处理
- 对于嵌套数据类型,可以使用UDF
- 纯JSON串可使用JsonSerDe处理更简单
错误速查
| 症状 | 根因 | 修复 |
|---|---|---|
| UDF 返回全是 NULL | jsonStr 为空/非法 JSON | 先判断 jsonStr 非空 |
| explode 后结果丢行 | UDF 返回 null 时 explode 不产生行 | 缺失字段返回空数组 |
| ClassNotFound | jar 未被下发到执行节点 | 使用带依赖的 fat-jar |
| JsonSerDe 建表后查询全 NULL | 字段名/类型与 JSON 不匹配 | 保证每行完整 JSON |