hive 存储,解析,处理json数据
hive 处理json数据总体来说有两个方向的路走
- 将json以字符串的方式整个入Hive表,然后通过使用UDF函数解析已经导入到hive中的数据,比如使用LATERAL VIEW json_tuple的方法,获取所需要的列名。
- 在导入之前将json拆成各个字段,导入Hive表的数据是已经解析过得。这将需要使用第三方的SerDe。
-
第一种:
-
get_json_object(string json_string, string path)
第一个参数填写json对象变量,第二个参数使用$表示json变量标识,然后用 . 或 [] 读取对象或数组;如果输入的json字符串无效,那么返回NULL。
每次只能返回一个数据项。{"id": 1701439105,"ids": [2154137571,3889177061,1496915057,1663973284],"total_number": 493} CREATE TABLE IF NOT EXISTS tmp_json_test ( json string ) STORED AS textfile ; load data local inpath '/root/hivedata/json_test.txt' overwrite into table tmp_json_test; select get_json_object(t.json,'$.id'), get_json_object(t.json,'$.total_number') from tmp_json_test t ;
-
lateral view json_tuple
select t2.* from tmp_json_test t1 lateral view json_tuple(t1.json, 'id', 'total_number') t2 as c1, c2;
-
第二种
{"id": 1701439105,"ids": [2154137571,3889177061,1496915057,1663973284],"total_number": 493}
http://www.congiu.net/hive-json-serde/ add jar /root/hivedata/json-serde-1.3.7-jar-with-dependencies.jar; CREATE TABLE tmp_json_array ( id string, ids array<string>, `total_number` int) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' STORED AS TEXTFILE;
load data local inpath '/root/hivedata/json_test.txt' overwrite into table tmp_json_array;
-
详解
-
json数据的处理
-
把json数据当成字符串来解析映射 使用hive内置json函数进行操作
+----------------------------------------------------+--+ | tmp_json_test.json | +----------------------------------------------------+--+ | {"id": 1701439105,"ids": [2154137571,3889177061,1496915057,1663973284],"total_number": 493} | +----------------------------------------------------+--+ --get_json_object(json字段,'$.变量' ) hive普通函数 一进一出 select get_json_object(json,'$.total_number') from tmp_json_test; select get_json_object(json,'$.id'),get_json_object(json,'$.total_number') from tmp_json_test; --json_tuple hive内置 UDTF 配合lateral view使用 select t2.* from tmp_json_test t1 lateral view json_tuple(t1.json, 'id', 'total_number') t2 as c1, c2;
-
使用第三方SerDe类或者自己实现SerDe类实现json数据切割 进而解析json.
-- 分隔符指定语法: row format delimited fields terminate by ',' delimited:使用hive默认的SerDe类来进行数据切割解析。 org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe 这时候在建表的时候可以不使用默认的SerDe类 自己实现或者第三方SerDe. http://www.congiu.net/hive-json-serde/1.3.7/cdh5/ --step1 下载第三方支持json的SerDe类 json-serde-1.3.7-jar-with-dependencies.jar --step2 把jar添加到hive的classpath中 add jar /root/hivedata/json-serde-1.3.7-jar-with-dependencies.jar; --step3 建表的时候 指定分隔符类使用第三方的 CREATE TABLE tmp_json_array ( id string, ids array<string>, `total_number` int) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' STORED AS TEXTFILE; --经过上述操作 在加载映射数据的时候 就完成了对json数据的解析动作
-
-
hive中的正则替换函数 regexp_replace
语法 regexp_replace(字段,'替换前内容','替换后内容') 替换的内容支持正则的语法
-
json数组的处理
[ { "website":"www.itcast.cn", "name":"wangjie" }, { "website":"cloud.itcast.com", "name":"carbondata 中文文档" } ]
[{"website":"www.itcast.cn","name":"wangjie"}, {"website":"cloud.itcast.com","name":"carbondata 中文文档"}]
第一步:把json数组中元素之间的分隔符 从 },{ 变成};{
select regexp_replace('[{"website":"www.itcast.cn","name":"wangjie"},{"website":"cloud.itcast.com","name":"carbondata 中文文档"}]','\\}\\,\\{','\\}\\;\\{');
结果
[{"website":"www.itcast.cn","name":"wangjie"};{"website":"cloud.itcast.com","name":"carbondata 中文文档"}]
第二步:把上一步的结果进行替换操作 把[|]替换成为""
select regexp_replace(regexp_replace('[{"website":"www.itcast.cn","name":"wangjie"},{"website":"cloud.itcast.com","name":"carbondata 中文文档"}]','\\}\\,\\{','\\}\\;\\{'),'\\[|\\]','');
结果
{"website":"www.itcast.cn","name":"wangjie"};{"website":"cloud.itcast.com","name":"carbondata 中文文档"}
第三步 根据分隔符; 进行切割 变成array(String)
第四步 把切割后的结果交给explode炸开 每个元素一行 每一行都是标准json数据。select json_tuple(json, 'website', 'name') from (SELECT explode(split(regexp_replace(regexp_replace('[{"website":"www.itcast.cn","name":"wangjie"},{"website":"cloud.itcast.com","name":"carbondata 中文文档"}]', '\\}\\,\\{','\\}\\;\\{'),'\\[|\\]',''),'\\;')) as json) itcast;
结果
www.itcast.cn,wangjie cloud.itcast.com,carbondata 中文文档
对于上述操作 阅读性极差 原因在于在一个sql中嵌套使用了过多的函数
解决:针对每一次函数的使用 创建中间临时表的方式存储中间结果。 insert+select