hive 解析 json 数据方法
json是常见的一种数据格式,一般通过埋点程序获取行为用户行为数据,将多个字段存放在一个json数组中,因此数据平台调用数据时,要对json数据进行解析处理。接下来介绍下Hive中是如何解析json数据的。
希望解析出以下数据:
实现思路:
explode函数
hive 解析 json 数据函数
1、get_json_object
- 语法:get_json_object(json_string, '$.key')
- 说明:解析json的字符串json_string,返回path指定的内容。如果输入的json字符串无效,那么返回NULL。这个函数每次只能返回一个数据项。
实例
select get_json_object('{"name":"令狐冲","age":29}', '$.name') user_name;
结果
解析二个字段示例:select get_json_object('{"name":"依琳","age":16}', '$.name') user_name, get_json_object('{"name":"依琳","age":16}', '$.age') user_age;
get_json_object解析json多个字段有很多会太麻烦,可以使用 json_tuple。
2、json_tuple
- 语法: json_tuple(json_string, k1, k2 ...)
- 说明:解析json的字符串json_string,可指定多个json数据中的key,返回对应的value。如果输入的json字符串无效,那么返回NULL。
示例
select b.user_name, b.age from (select * from temp.jc_test_coalesce_nvl where c1 = 1) i lateral view json_tuple('{"name":"依琳","age":18}', 'name', 'age') b as user_name, age;
json_tuple 使用细节:与 get_json_object 不同,使用 json_tuple 获取数据不需要使用 $,如果使用 $ 反而获取不到数据。
select b.user_name, b.age from (select * from temp.jc_test_coalesce_nvl where c1 = 1) i lateral view json_tuple('{"name":"依琳","age":18}', '$.name', '$.age') b as user_name, age;结果:使用json_tuple时需注意这一点
小结:json_tuple相当于get_json_object的优势就是一次可以解析多个json字段。但是这两个函数都无法处理json数组。
hive 解析 json 数组
1、使用嵌套子查询解析json数组
场景:一个hive表有 json_str 字段的内容如下:
| json_str |
| [{"title":"笑傲镜湖","author":"金庸"},{"title":"小李飞刀","author":"古龙"}] |
| title | author |
| 笑傲镜湖 | 金庸 |
| 小李飞刀 | 古龙 |
- 语法:explode(Array OR Map)
- 说明:explode()函数接收一个array或者map类型的数据作为输入,然后将array或map里面的元素按照每行的形式输出,即将hive一列中复杂的array或者map结构拆分成多行显示,也被称为列转行函数。
示例
select array('A','B','C') ;
select explode(array('A','B','C'));
regexp_replace函数
- 语法: regexp_replace(string A, string B, string C)
- 说明:将字符串A中的符合java正则表达式B的部分替换为C。注意,在有些情况下要使用转义字符,类似oracle中的regexp_replace函数。
select regexp_replace('hive_spark', 've_sp', '@');下面我们试着解析 json 数组 第一步:先将json数组中的元素解析出来,转化为每行显示
select explode(split(regexp_replace(regexp_replace('[{"title":"笑傲镜湖","author":"金庸"},{"title":"小李飞刀","author":"古龙"}]', '\\[|\\]',''),'\\}\\,\\{','\\}\\;\\{'),'\\;')); 结果: "{""title"":""笑傲镜湖"",""author"":""金庸""}" "{""title"":""小李飞刀"",""author"":""古龙""}"上面SQL看着很长,但是一步一步看也很 esay
select explode(split( regexp_replace( regexp_replace( '[ {"title":"笑傲镜湖","author":"金庸"}, {"title":"小李飞刀","author":"古龙"} ]', '\\[|\\]' , ''), --将json数组两边的中括号去掉 '\\}\\,\\{' , '\\}\\;\\{'),--将json数组元素之间的逗号换成分号 '\\;') --以分号作为分隔符(split函数以分号作为分隔) );说明:为什么要将json数组元素之间的逗号换成分号? 因为元素内的分隔也是逗号,如果不将元素之间的逗号换掉的话,后面用split函数分隔时也会把元素内的数据给分隔,这不是我们想要的结果。 第二步、上步已经把一个json数组转化为多个json字符串了,接下来使用json_tuple函数来解析json里面的字段:
select json_tuple(explode(split(regexp_replace(regexp_replace('[{"title":"笑傲镜湖","author":"金庸"},{"title":"小李飞刀","author":"古龙"}]', '\\[|\\]', ''),'\\}\\,\\{', '\\}\\;\\{'), '\\;')) , 'title', 'author') ;执行上述语句,结果报错了:
UDTF's are not supported outside the select clause, nor nested in expressions:17:16,explode函数不能写在别的json_tuple里面,更正使用子查询方式
select json_tuple(json, 'title', 'author') from ( select explode(split(regexp_replace(regexp_replace('[{"title":"笑傲镜湖","author":"金庸"},{"title":"小李飞刀","author":"古龙"}]', '\\[|\\]', ''),'\\}\\,\\{', '\\}\\;\\{'), '\\;')) as json) o
2、使用 lateral view 解析json数组
样例数据如下select party_name, user_name_ from temp.jc_t_test_json lateral view explode(user_name) tmp_table as user_name_;按照 user_name_ 进行分组聚合即可:
select user_name_ ,count(party_name) name_cnt from temp.jc_t_test_json lateral view explode(user_name) tmp_table as user_name_ group by user_name_;下面看下刚才遇到的用UDTF的时候,SELECT 只支持一个字段的问题
select good_id,get_json_object(sale_json,'$.monthsales') as monthsales from tablename lateral view explode(split(goods_id,','))goods as good_id lateral view explode(split(regexp_replace(regexp_replace(json_str , '\\[|\\]',''),'\\}\\,\\{','\\}\\;\\{'),'\\;')) sales as sale_json;
| goods_id | monthSales |
| 1 | 4900 |
| 1 | 2090 |
| 1 | 6987 |
| 2 | 4900 |
| 2 | 2090 |
| 2 | 6987 |
| 3 | 4900 |
| 3 | 2090 |
| 3 | 6987 |