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

主要类型

  1. 普通 UDF:单行输入单行输出
  2. UDAF:多行输入单行输出,聚合函数
  3. 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 返回全是 NULLjsonStr 为空/非法 JSON先判断 jsonStr 非空
explode 后结果丢行UDF 返回 null 时 explode 不产生行缺失字段返回空数组
ClassNotFoundjar 未被下发到执行节点使用带依赖的 fat-jar
JsonSerDe 建表后查询全 NULL字段名/类型与 JSON 不匹配保证每行完整 JSON