前言
最近一位开发的同学在使用get_json_object函数对json数据解析的时候,出现了结果为null的问题,问题原因是sql语法导致的,那么今天就来详细介绍一下解析json函数的用法!
一、了解hive中处理json的两个函数
1. get_json_object函数
先看看这个函数具体是如何定义的:
执行命令:
desc function extended get_json_object;
执行结果:
get_json_object(json_txt, path) - Extract a json object from path Extract json object from a json string based on json path specified, and return json string of the extracted json object. It will return null if the input json string is invalid. A limited version of JSONPath supported: $ : Root object . : Child operator [] : Subscript operator for array * : Wildcard for [] Syntax not supported that's worth noticing: '' : Zero length string as key .. : Recursive descent @ : Current object/element () : Script expression ?() : Filter (script) expression. [,] : Union operator [start:end:step] : array slice operator Function class:org.apache.hadoop.hive.ql.udf.UDFJson Function type:BUILTIN
从执行结果来看,
- get_json_object 有两个参数:json_txt, path
json_txt:需要解析的json字符串数据。
path:json中的 ‘路径’,
其需要遵守如下的规则:
$ : Root object 表示根对象,即整个json . : Child operator 表示用.来关联子路径 [] : Subscript operator for array 表示如果子路径为数组类型,需要用[]来获取数据 * : Wildcard for [] 表示使用[]的时候,支持通配符*
- 函数类路径:org.apache.hadoop.hive.ql.udf.UDFJson
2. json_tuple函数
再看下json_tuple的
执行命令:
desc function extended json_tuple;
执行结果:
json_tuple(jsonStr, p1, p2, ..., pn) - like get_json_object, but it takes multiple names and return a tuple. All the input parameters and output column types are string. Function class:org.apache.hadoop.hive.ql.udf.generic.GenericUDTFJSONTuple Function type:BUILTIN
从执行结果来看:
- json_tuple 可以传多个参数,jsonStr, p1, p2, …, pn,
jsonStr:需要解析的json字符串数据。
p1, p2, …, pn:json中的多个 ‘路径’
返回一个元组,所有输入参数和输出列的数据为sting类型。 - 函数类路径:org.apache.hadoop.hive.ql.udf.generic.GenericUDTFJSONTupl
二、解析简单json
给定如下测试数据:
{"id":1,"name":"zhangsan"}
1. 想要解析name,可以使用get_json_object:
select get_json_object('{"id":1,"name":"zhangsan"}', "$.name");
也可以使用json_tuple :
select json_tuple('{"id":1,"name":"zhangsan"}', "name");
2. 想同时提取所有字段,可以用json_tuple
select json_tuple('{"id":1,"name":"zhangsan"}', "id","name");
也可以使用get_json_object
select get_json_object('{"id":1,"name":"zhangsan"}', "$.id"),get_json_object('{"id":1,"name":"zhangsan"}', "$.name");
三、解析json数组
给定如下测试数组数据:
[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]
1. 提取数组中第一条数据的name
select get_json_object('[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]', "$.[0].name"); 或 select get_json_object('[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]', "$[0].name");
2. 提取数组中所有的name
select get_json_object('[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]', "$.[*].name"); 或 select get_json_object('[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]', "$[*].name");
四、解析嵌套json
给定如下测试嵌套json数据:
{"class":[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]}
1. 提取class字段下数组
select get_json_object('{"class":[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]}', "$.class");
2. 提取class字段下数组的name
select get_json_object('{"class":[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]}', "$.class[*].name"); 或 select get_json_object('{"class":[{"id":1,"name":"zhangsan"},{"id":2,"name":"lisi"},{"id":3,"name":"wangwu"}]}', "$.class.name");
注意:
Tez引擎是支持上面两种写法的,即"$.class[].name"和"$.class.name";
但是spark引擎只支持"$.class[].name"写法,而不支持"$.class.name",不然就会解析成null!这个也是前文提到的结果为null的原因!
总结
最后还是提醒小伙伴们,在开发过程中,一定要注意sql语法格式的书写,避免一些意想不到的结果!