前言
JSON的话在实际开发中大量使用了,常规的解析操作直接一把百度就可以查到了,不过总有一些犄角旮旯的需求让人抓狂,今天对JSON部分操作进行一些梳理,方便碰到之后在这里可以查询。
GET_JSON_OBJECT
命令格式
string get_json_object(string <json>, string <path>)
需要注意的是第二个参数其实是path,实际是如下的使用,蛮多人对那个$.a云里雾里,这里头到底写啥呢,我比较喜欢找到原始的出处,其实是在Hive上面有对这个进行说明,链接,对应描述如下:
get_json_object
A limited version of JSONPath is supported:
$ : Root object 美元符号,代表根对象
. : Child operator 点号,代表子节点的操作
[] : Subscript operator for array 中括号,数组的下标操作符,[0],[1]..这种
* : Wildcard for []其实是表示数组操作的通配符[*],这样子就是全部的元素了
总体来说其实里面的规则不多,就是支持$.[]*这几种操作,当然这些操作已经可以满足我们大部分需求了,我们测试一下官网给出的例子:
{
"store": {
"fruit": [{
"weight": 8,
"type": "apple"
}, {
"weight": 9,
"type": "pear"
}],
"bicycle": {
"price": 19.95,
"color": "red"
}
},
"email": "amy@only_for_json_udf_test.net",
"owner": "amy"
}
SELECT get_json_object(json, '$.owner') FROM src_json;
结果:
amy
SELECT get_json_object(json, '$.store.fruit[0]') FROM src_json;
结果:
{"weight":8,"type":"apple"}
SELECT get_json_object(json, '$.non_exist_key') FROM src_json;
结果:
NULL
数组操作
select GET_JSON_OBJECT(json, '$.store.fruit[*]') AS fruits from src_json
结果:
[{
"weight": 8,
"type": "apple"
}, {
"weight": 9,
"type": "pear"
}]
FROM_JSON
命令格式
from_json(<jsonStr>, <schema>)
根据JSON字符串jsonStr和schema信息,返回ARRAY、MAP或STRUCT类型。当我们需要进行一些复杂的操作的时候,需要对把JSON加工成对象形式,可以进一步提取信息。
举例说明:在上面一步操作上,我们已经fruit信息进行提前,但是有个情况,我们其实看到结果就是一行数据,我们希望每一个水果的内容都是一行信息,完整sql如下:
select fruit['type'] as type,fruit['weight'] as weight from (
select explode(from_json(GET_JSON_OBJECT(json, '$.store.fruit[*]'),'array<map<string, string>>')) AS fruit from values ('
{
\"store\": {
\"fruit\": [{
\"weight\": 8,
\"type\": \"apple\"
}, {
\"weight\": 9,
\"type\": \"pear\"
}],
\"bicycle\": {
\"price\": 19.95,
\"color\": \"red\"
}
},
\"email\": \"amy@only_for_json_udf_test.net\",
\"owner\": \"amy\"
}') src_json(json)
)
结果如下:
from_json函数实现了把原有的json数组进行映射array<map<string, string>>,得到的数组通过explode展开
map_keys 获取key
这个udf不复杂,就是提取key,只不过一时半会想不到,提取key的场景少很多,但是需要的时候就头大。
select map_keys(from_json(json,'map<string,string>'))
from values('{"a":1,"b":2}') src_json(json)
结果:[a, b]
可以看到,如果需要变成一行行数据的话也需要通过explode展开:
select explode(map_keys(from_json(json,'map<string,string>'))) as key
from values('{"a":1,"b":2}') src_json(json)
集合操作
有了前面的基础,可以通过json提取之后配合一些集合的操作,例如,前面的fruit我需要提取type='apple’怎么去做,方法一:通过最后来一个where条件,也可以,方法二就是通过filter集合操作来运算:
select fruit['type'] as type,fruit['weight'] as weight from (
select explode(filter(from_json(GET_JSON_OBJECT(json, '$.store.fruit[*]'),'array<map<string, string>>'),x->x['type']='apple')) AS fruit from values ('
{
\"store\": {
\"fruit\": [{
\"weight\": 8,
\"type\": \"apple\"
}, {
\"weight\": 9,
\"type\": \"pear\"
}],
\"bicycle\": {
\"price\": 19.95,
\"color\": \"red\"
}
},
\"email\": \"amy@only_for_json_udf_test.net\",
\"owner\": \"amy\"
}') src_json(json)
)
结果如下:
|