文章目录
关于json:
https://blog.csdn.net/atwdy/article/details/124668815
1.HiveSQL中两个json解析函数
1)get_json_object
$
:代表json的根对象,即传入的json本身。(对象{ },或对象数组[{ }, { }, …])
.
:父子层级关系
[]
:用于指定对象数组中要解析对象的下标,起始0
*
:通配符,用在
[]
中,表示取
[]
中所有对象。(通配符个人认为适用的场景为取同一层级所有对象的某个属性时,如果是取所有对象本身,那么直接不加
[]
也是一样的效果)
demo
-- 测试jsoncreatetemporaryview test asselect'[
{
"name": "张三",
"age": 20,
"sport": ["篮球", "乒乓球"]
},
{
"name": "李四",
"age": 20,
"sport": ["足球", "羽毛球"]
}
]'as json_str;-- 取根对象,也就是传入的json本身-- [{"name":"张三","age":20,"sport":["篮球","乒乓球"]},{"name":"李四","age":20,"sport":["足球","羽毛球"]}]select get_json_object(json_str,'$')from test;-- 取根对象数组中的第一个对象:张三-- {"name":"张三","age":20,"sport":["篮球","乒乓球"]}select get_json_object(json_str,'$[0]')from test;-- 取根数组中所有对象的年龄,返回值为数组形式的字符串,不去重,忽略null值-- [20,20]select get_json_object(json_str,'$[*].age')from test;
2)json_tuple
和get_json_object不同的是,get_json_object是一个普通的UDF函数,返回的是一个值。而json_tuple是一个UDTF函数,返回的是一个表,所以开发中为了关联原表相关信息该函数一般需要和lateral view侧视图
https://blog.csdn.net/atwdy/article/details/137614216连用。
demo
-- 测试jsoncreatetemporaryview test asselect'1'as id,'{"name": "张三", "age": 20, "sport": ["篮球", "乒乓球"]}'as info
unionallselect'2'as id,'{"name": "李四", "age": 20, "sport": ["足球", "羽毛球"]}'as info;select*from test;
select json_tuple(info,'name','age','sport')from test;
lateral view 关联原表信息:
select
t1.id,
t2.*from test t1
lateral view json_tuple(info,'name','age','sport') t2 as name, age, sport;
官网中只说了需要通过lateral view关联原表信息,但实际测试中发现
select id, json_tuple(info, 'name', 'age', 'sport') as (name, age, sport) from test;
这种语法格式也能输出上图结果。虽然逻辑上理解并不矛盾,尽管该UDTF返回的是个表,但一行输入只会对应一行输出,只是输出的字段可能是多个,并不像explode那样返回的是多行。所以不会出现一行输入对应多行输出的情况。但官方文档中没有提到这种语法,为了准确还是按照侧视图实现比较稳妥。
2.json中key所在层级路径定位小工具
对于一个复杂的json串,解析某个key时人工查找该key所在路径效率低也容易出错,下面代码可以快速找到指定key第一次出现时所在的层级路径:
#!/usr/bin/env python3# -*-coding:utf-8 -*-"""
@desc: 查找json中key第一次出现时的所在层级路径,key不存在返回None
@time: 2024/8/4 01:52
"""import json
deffind_path(json_obj, key, path=None):if path isNone:
path =[]ifisinstance(json_obj,dict):if key in json_obj:return path +[key]for k, v in json_obj.items():
p = find_path(v, key, path +[k])if p isnotNone:return p
elifisinstance(json_obj,list):for i, v inenumerate(json_obj):
p = find_path(v, key, path +[str(i)])if p isnotNone:return p
returnNoneif __name__ =='__main__':
json_file =r'./data.json'withopen(json_file,'r', encoding='utf8')as fin:
json_obj = json.load(fin)
path = find_path(json_obj, key='broadcast_desc')print(path)
版权归原作者 atwdy 所有, 如有侵权,请联系我们删除。