hive中自定义JsonSerde处理复杂结构的json数据

时间:2022-02-21 09:44:36

使用背景

hive自身提供UDF函数get_json_object 支持json数据的操作,但是使用效果并不是非常理想。如果可以像普通hive建表指定字段映射到json中的key就太好了!幸好hive本身提供了数据序列化反序列化的接口Serde,开发者只需要自定义实现Serde接口实现自己的逻辑即可。下面介绍的是通过开源工具Hive-JSON-Serde-develop来实现的序列化反序列化操作实例。

具体介绍

1.下载Hive-JSON-Serde-develop源码,自己编译打成jar包:JsonSerde.jar;
2.将jar包放到HIVE_HOME的auxlib目录下,然后修改hive-env.sh,添加HIVE_AUX_JARS_PATH=$HIVE_HOME/auxlib/JSONSerDe.jar,这样每次运行hive客户端的时候都会将这个jar包添加到classpath中
3.编写hive建表语句,并保存到create_json_tab.hql文本中。下面附上我的业务数据json结构;

create external table if not exists json_tab (
`_area` string,
`_name` string,
`_sex` string,
`_uuid` string,
`nickname` array<struct<`_trust`:float, `_vtime`:array<string>, `val`:string>>,
`addr` array<struct<`_trust`:float, `_vtime`:array<string>, `val`:string>>,
`qq` array<struct<`_trust`:float, `_vtime`:array<string>, `val`:string>>,
`email` array<struct<`_trust`:float, `_vtime`:array<string>, `val`:string>>,
`tel` array<struct<`_trust`:float, `_vtime`:array<string>, `val`:string>>,
`refer` array<map<string, string>>,
`conflict` array<map<string, string>>
)
-- 指定Serde类
row format serde "org.openx.data.jsonserde.JsonSerDe"
stored as textfile
-- 指定json数据位置
location '/data/test/json/';

4.执行 hive -f create_json_tab.hql 生成对应表并加载数据;
5.测试,编写sql进行测试。

注意

  1. 由于我的json数据结构比较复杂,包含大量的Array, Map, Struct嵌套,所以get_json_object函数使用起来不方便,但是对于普通结构的json数据来说,该函数完全可以胜任,而且非常方便
  2. 字段映射:JsonSerde默认采用的是同名映射,将json数据中的key映射到hive表中相同名字的字段上。jsonArray结构自动隐射成hive Array结构,jsonObject结构自动隐射成hive Map或者Struct结构
  3. hive保留字符:hive本身包含若干保留字符,开发者可以通过在建表语句中添加WITH SERDEPROPERTIES(‘table’=’tab’),并指定字段别名,比如说,如果json中的key是“table”,可以将其指定映射成hive表中的“tab”字段,这样就避免了保留字符冲突
  4. hive表中的字段默认是不允许使用下划线“_”开头的,但是如果我们想保证hive表字段和json key一致的话,可以使用英文输入法状态下的飘号(tab键上面的 “)将字段包含起来,这样既可正确创建字段。具体见上面的sql语句。