Hive系列之解析JSON数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive系列之解析JSON数据相关的知识,希望对你有一定的参考价值。


概述

在数据处理中,经常遇到的一个数据类型就是JSON,mysql数据库解析JSON,参考​​MySQL 5.7 JSON函数学习​​,
​MySQL json_merge with group by​​。

在大数据执行引擎Hive中,我们也经常会遇到JSON解析的场景。

实战

get_json_object、json_tuple

Hive内部提供大量的内置函数用于处理各种类型的需求,参见官方文档:​​Hive Operators and User-Defined Functions (UDFs)​​​。从这些内置的 UDF 可找到两个用于解析JSON的函数:​​get_json_object​​​ 和 ​​json_tuple​​。

​get_json_object​​​ 语法:​​get_json_object(STRING json_string, STRING path)​

​get_json_object​​​一个只能取一个字段:​​SELECT get_json_object("name":"johnny","sex":"男", $.name);​​​ 输出:​​johnny​

如果想要取多个字段,这么写:
​​​SELECT get_json_object("name":"johnny","sex":"男", $.name), get_json_object("name":"johnny","sex":"男", $.sex);​​​ 输出:​​johnny 男​

json_tuple 相对于 get_json_object 的优势:一次可以解析多个JSON字段。

语法:​​json_tuple(STRING jsonStr, STRING k1, STRING k2)​

实例:​​SELECT json_tuple("name":"johnny","sex":"男", name, sex);​​​ 输出:​​johnny 男​

但是如果有个JSON数组,​​get_json_object​​​处理JSON数组的功能很有限:
​​​SELECT get_json_object(["name":"johnny","sex":"男", "name":"lucy","sex":"女"], $.[0].name);​​ 输出:johnny

如果想将整个JSON数组里面的name字段都解析出来,如果这么写将非常麻烦,因为无法确定数组的长度,而且即使确定,由于指定索引字段,可维护性很差。

explode

Hive内置函数

explode() takes in an array (or a map) as an input and outputs the elements of the array (map) as separate rows. UDTFs can be used in the SELECT expression list and as a part of LATERAL VIEW。

​explode()​​接收一个 array 或 map 类型的数据作为输入,然后将 array 或 map 里面的元素按照每行的形式输出。可配合 LATERAL VIEW 一起使用。

比如:

select explode(array(A,B,C));
A
B
C
select explode(map(A,10,B,20,C,30));
A 10
B 20
C 30

用于解析JSON:

SELECT explode(split(regexp_replace(regexp_replace(["name":"johnny","sex":"男", "name":"lucy","sex":"女"], ,\\\\\\\\;\\\\),\\\\[|\\\\],),\\\\;));

输出:

"name":"johnny","sex":"男"
"name":"lucy","sex":"女"

几点说明:

  • explode 函数只能接收数组或 map 类型的数据,而 split 函数生成的结果就是数组;
  • 第一个 regexp_replace,外层的那个:将JSON数组元素之间的逗号换成分号
  • 第二个 regexp_replace,内层的那个:将JSON数组两边的中括号去掉

然后可以结合 get_json_object 或 json_tuple 来解析里面的字段:

select json_tuple(json, name, sex) from(SELECT
explode(split(regexp_replace(regexp_replace(["name":"johnny","sex":"男", "name":"lucy","sex":"女"], \\\\\\\\,\\\\,\\\\\\\\;\\\\),\\\\[|\\\\],),\\\\;))
as json) iteblog;

输出:

johnny 男
lucy 女

自定义函数解析JSON数组

<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>2.1.1</version>
</dependency>

Hive提供强大的自定义函数接口,故可自定义解析JSON数组的UDF:

package com.johnny.demo;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
@Description(name = "json_array", value = "_FUNC_(array_string) - Convert a string of a JSON-encoded array to a Hive array of strings.")
public class UDFJsonAsArray extends UDF
public ArrayList evaluate(String jsonString)
if (jsonString == null)
return null;

try
JSONArray extractObject = new JSONArray(jsonString);
ArrayList result = new ArrayList();
for (int ii = 0; ii < extractObject.length(); ++ ii)
result.add(extractObject.get(ii).toString());

return result;
catch (JSONException | NumberFormatException e)
return null;


使用:

hive> add jar /root/json.jar;
hive> create temporary function json_array as com.johnny.demo.UDFJsonAsArray;
hive> select explode(json_array(["name":"johnny","sex":"男", "name":"lucy","sex":"女"]));
OK
"name":"johnny","sex":"男"
"name":"lucy","sex":"女"
hive> select json_tuple(json, name, sex) from
(SELECT explode(json_array(["name":"johnny","sex":"男", "name":"lucy","sex":"女"])) as json) iteblog;
johnny 男
lucy 女

参考

如何在 Apache Hive 中解析JSON数组


以上是关于Hive系列之解析JSON数据的主要内容,如果未能解决你的问题,请参考以下文章

大话JSON之Gson解析JSON

一个解析json串并组装echarts的option的函数解析

Hive解析Json数据

实时即未来,大数据项目车联网之原始数据实时ELT流式任务流程总结

实时即未来,大数据项目车联网之原始数据实时ELT流式任务流程总结

hive 存储,解析,处理json数据