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串并组装echarts的option的函数解析
实时即未来,大数据项目车联网之原始数据实时ELT流式任务流程总结