hive ( default )> SELECT get_json_object( '{"website":"www.iteblog.com","name":"过往记忆"}' , '$.website' );
www.iteblog.com
hive ( default )> SELECT json_tuple( '{"website":"www.iteblog.com","name":"过往记忆"}' , 'website' , 'name' );
www.iteblog.com 过往记忆
Time taken: 0.074 seconds, Fetched: 1 row(s)
hive ( default )>
> SELECT get_json_object( '[{"website":"www.iteblog.com","name":"过往记忆"}, {"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}]' , '$.[0].website' );
www.iteblog.com
Time taken: 0.069 seconds, Fetched: 1 row(s)

如果我们想将整个 Json 数组里面的 website 字段都解析出来,如果这么写将非常麻烦,因为我们无法确定数组的长度,而且即使确定了,这么写可维护性也很差,所以我们需要想别的办法。

如何在 Apache Hive 中解析 Json 数组
如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号: iteblog_hadoop

使用 Hive 自带的函数解析 Json 数组

在介绍如何处理之前,我们先来了解下 Hive 内置的 explode 函数,官方的解释是: 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 一起使用。光看文字描述很不直观,咱们来看看几个例子吧。

Time taken: 4.188 seconds, Fetched: 3 row(s)
hive ( default )> select explode(map( 'A' ,10, 'B' ,20, 'C' ,30));
hive ( default )> SELECT explode(split(regexp_replace(regexp_replace( '[{"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}]' , '{' , '\\}\\;\\{' ), '\\[|\\]' , '' ), '\\;' ));
{ "website" : "www.iteblog.com" , "name" : "过往记忆" }
{ "website" : "carbondata.iteblog.com" , "name" : "carbondata 中文文档" }
  • explode 函数只能接收数组或 map 类型的数据,而 split 函数生成的结果就是数组;
  • 第一个 regexp_replace 的作用是将 Json 数组元素之间的逗号换成分号,所以使用完这个函数之后, [{"website":"www.iteblog.com","name":"过往记忆" },{ "website":"carbondata.iteblog.com","name":"carbondata 中文文档"}] 会变成 [{"website":"www.iteblog.com","name":"过往记忆" };{ "website":"carbondata.iteblog.com","name":"carbondata 中文文档"}]
  • 第二个 regexp_replace 的作用是将 Json 数组两边的中括号去掉,所以使用完这个函数之后, [ {"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"} ] 会变成 {"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}
  • hive ( default )> select json_tuple(json, 'website' , 'name' ) from ( SELECT explode(split(regexp_replace(regexp_replace( '[{"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondateblog.com","name":"carbondata 中文文档"}]' , '\\}\\,\\{' , '\\}\\;\\{' ), '\\[|\\]' , '' ), '\\;' )) as json) iteblog;
    www.iteblog.com 过往记忆
    carbondata.iteblog.com  carbondata 中文文档
    Time taken: 0.189 seconds, Fetched: 2 row(s)
    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<String> evaluate(String jsonString) {
    if (jsonString == null ) {
    return null ;
    try {
    JSONArray extractObject = new JSONArray(jsonString);
    ArrayList<String> result = new ArrayList<String>();
    for ( int ii = 0 ; ii < extractObject.length(); ++ii) {
    result.add(extractObject.get(ii).toString());
    return result;
    } catch (JSONException e) {
    return null ;
    } catch (NumberFormatException e) {
    return null ;
    hive ( default )> add jar /home/iteblog/iteblog.jar;
    Added [/home/iteblog/iteblog.jar] to class path
    Added resources: [/home/iteblog/iteblog.jar]
    hive ( default )> create temporary function json_array as 'com.iteblog.udf.json.UDFJsonAsArray' ;
    Time taken: 0.013 seconds
    hive ( default )>
    > select explode(json_array( '[{"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}]' ));
    { "website" : "www.iteblog.com" , "name" : "过往记忆" }
    { "website" : "carbondata.iteblog.com" , "name" : "carbondata 中文文档" }
    Time taken: 0.08 seconds, Fetched: 2 row(s)
    hive ( default )> select json_tuple(json, 'website' , 'name' ) from ( SELECT explode(json_array( '[{"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbta 中文文档"}]' )) as json) iteblog;
    www.iteblog.com 过往记忆
    carbondata.iteblog.com  carbondata 中文文档
    Time taken: 0.082 seconds, Fetched: 2 row(s)