我们都知道,Hive 内部提供了大量的内置函数用于处理各种类型的需求,参见官方文档:Hive Operators and User-Defined Functions (UDFs)。我们从这些内置的 UDF 可以看到两个用于解析 Json 的函数:get_json_object 和 json_tuple。用过这两个函数的同学肯定知道,其职能解析最普通的 Json 字符串,如下:

hive (default)>  SELECT get_json_object('{"website":"www.iteblog.com","name":"过往记忆"}', '$.website');
OK
www.iteblog.com
 
hive (default)> SELECT json_tuple('{"website":"www.iteblog.com","name":"过往记忆"}', 'website', 'name');
OK
www.iteblog.com 过往记忆
Time taken: 0.074 seconds, Fetched: 1 row(s)

json_tuple 相对于 get_json_object 的优势就是一次可以解析多个 Json 字段。但是如果我们有个 Json 数组,这两个函数都无法处理,get_json_object 处理 Json 数组的功能很有限,如下:

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

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


如果想及时了解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 一起使用。光看文字描述很不直观,咱们来看看几个例子吧。

hive (default)> select explode(array('A','B','C'));
OK
A
B
C
Time taken: 4.188 seconds, Fetched: 3 row(s)
 
hive (default)> select explode(map('A',10,'B',20,'C',30));
OK
A 10
B 20
C 30

相信不需要我描述大家就能看明白这个函数的意义。大家可能会问,这个函数和我们解析 Json 数组有毛关系啊。其实有关系,我们其实可以使用这个函数将 Json 数组里面的元素按照一行一行的形式输出。根据这些已有的知识,我们可以写出以下的 SQL 语句:

hive (default)> SELECT explode(split(regexp_replace(regexp_replace('[{"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}]', '{','\\}\\;\\{'),'\\[|\\]',''),'\\;'));
OK
{"website":"www.iteblog.com","name":"过往记忆"}
{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}

现在我们已经能正确的解析 Json 数据了。

你现在肯定不知道上面一堆的 SQL 是啥含义,这里我来一步一步的解释。

  • 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 中文文档"}

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

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;
OK
www.iteblog.com 过往记忆
carbondata.iteblog.com  carbondata 中文文档
Time taken: 0.189 seconds, Fetched: 2 row(s)

自定义函数解析 Json 数组

虽然可以使用 Hive 自带的函数类解析 Json 数组,但是使用起来还是有些麻烦。值得高兴的是, Hive 提供了强大的自定义函数(UDF)的接口,我们可以使用这个功能来编写解析 Json 数组的 UDF。具体的代码如下:

package com.iteblog.udf.json;
 
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;
        }
    }
}

上面的代码逻辑很简单,我就不介绍了。将上面的代码进行编译打包,假设打包完的 jar 包名称为 iteblog.jar,然后我们就可以如下使用这个函数了。

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';
OK
Time taken: 0.013 seconds
hive (default)>
              > select explode(json_array('[{"website":"www.iteblog.com","name":"过往记忆"},{"website":"carbondata.iteblog.com","name":"carbondata 中文文档"}]'));
OK
{"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;
OK
www.iteblog.com 过往记忆
carbondata.iteblog.com  carbondata 中文文档
Time taken: 0.082 seconds, Fetched: 2 row(s)

这个结果和上面使用 Hive 内置的函数结果一致。当然,你还可以实现其他的 UDF,逻辑和这个类似,就不再介绍了。

如何在 Apache Hive 中解析 Json 数组的更多相关文章

  1. hive中解析json数组

    -- hive中解析json数组 select t1.status ,substr(ss.col,,) as col ,t3.evcId ,t3.evcLicense ,t3.evcAddress , ...

  2. Hive解析Json数组超全讲解

    在Hive中会有很多数据是用Json格式来存储的,如开发人员对APP上的页面进行埋点时,会将多个字段存放在一个json数组中,因此数据平台调用数据时,要对埋点数据进行解析.接下来就聊聊Hive中是如何 ...

  3. Android 中解析 JSON

    有什么不懂的可以去官网去看看:www.json.org 在google android中也有关于解析JSON的类库:JsonReader,但是只能在3.0以后的版本中才可以用,在这里我们用google ...

  4. 使用QtScript库解析Json数组例子

    本文转载自:http://blog.sina.com.cn/s/blog_671732440100uwxh.html 使用qtscipt库解析json数组首先在工程文件中加 QT        += ...

  5. android 中解析json格式数据

    本文来自http://tonysun3544.iteye.com/category/188238 package com.tony.json; import android.app.Activity; ...

  6. Jquery解析json数组字符串

    最近在工作中用到了Jquery来解析json字符串,网上解析jquery解析json单个对象的实例不少,但是jquery解析json数组的实例却是不多,下面我举一个简单的例子来跟大家分享与一下,本人水 ...

  7. fastjson解析json数组

    1.fastjson解析json数组(直接上代码) import java.util.ArrayList; import java.util.List; import com.alibaba.fast ...

  8. JavaScript中解析JSON --- json.js 、 json2.js 以及 json3.js的使用区别

    JSON官方(http://www.json.org/)提供了一个json.js,json.js是JSON官方提供的在JavaScript中解析JSON的js包,json.js.json2.js.js ...

  9. c# 使用Newtonsoft.Json解析JSON数组

    一.获取JSon中某个项的值 要解析格式: [{"VBELN":"10","POSNR":"10","RET_ ...

随机推荐

  1. PHP在线批量下载文件

    在项目开发中需要给客户提供在线下载文件的功能. 解决方案:使用PHP自带的ZipArchive类,将多个文件打包成zip文件,供客户下载! 使用ZipArchive类时,需要先开启php_zip扩展, ...

  2. Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)

    Ajax跨域问题及解决方案   目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...

  3. C#中的事件的订阅与发布

    认识发布者/订阅者模式 发布者定义一系列事件,并提供一个注册方法: 订阅者向发布者注册自己的事件处理逻辑,供一个可被回调的方法,也就是事件处理程序:当发布者的事件被触发的时候,订阅者将通过回调函数得到 ...

  4. 项目Beta冲刺(5/7)(追光的人)(2019.5.27)

    所属课程 软件工程1916 作业要求 Beta冲刺博客汇总 团队名称 追光的人 作业目标 描述Beta冲刺每日的scrum和PM报告两部分 队员学号 队员博客 221600219 小墨 https:/ ...

  5. python连接redis哨兵集群

    一.redis集群模式有多种, 哨兵模式只是其中的一种实现方式, 其原理请自行谷歌或者百度 二.python 连接 redis 哨兵集群 1. 安装redis包 pip install redis 2 ...

  6. git在windows及linux(源码编译)环境下安装

    git在windows下安装 下载地址:https://git-scm.com/ 默认安装即可 验证 git --version git在linux下安装 下载地址:https://mirrors.e ...

  7. 【Redis】远程访问不了

    Windows安装后,启动的服务配置文件是redis.windows-service.conf "D:\Program Files\Redis\redis-server.exe" ...

  8. live-pusher属性值的改变

    例如:组件推流过程中,切换前后摄像头时,要改变mirror的值并使其生效: LivePusherContext = wx.createLivePusherContext() 1. LivePusher ...

  9. GAME-BASED LEARNING

    https://collegestar.org/modules/game-based-learning Introduction   Appalachian State University Game ...

  10. Linux安装pycharm并添加图标到桌面

    安装: 1.到pycharm官网下载Linux版本的pycharm包. 2.打开中端 cd到下载的文件夹,默认为 ~/Downloads/ 文件夹下 3.执行命令 tar -xvzf pycharm- ...