在工作中我们会经常遇到JSON格式的日志数据,本文来详细介绍在Hive中解析JSON字符串的函数:
1.get_json_object
2.json_tuple
这里直接上百度百科的解释:
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。
对象和数组是比较特殊且常用的两种类型。
对象:对象在 JS 中是使用花括号包裹 {} 起来的内容,数据结构为 {key1:value1, key2:value2, ...} 的键值对结构。在面向对象的语言中,key 为对象的属性,value 为对应的值。键名可以使用整数和字符串来表示。值的类型可以是任意类型。
例如下面这样,其中user_id和platform是key,也就是我们要解析出来的列名,10000和ios是value,也就是我们要解析出来的数据内容:
{"user_id": "10000", "platform": "ios"}
数组:数组在 JS 中是方括号 [] 包裹起来的内容,数据结构为 ["java", "javascript", "vb", ...] 的索引结构。在 JS 中,数组是一种比较特殊的数据类型,它也可以像对象那样使用键值对,但还是索引使用得多。同样,值的类型可以是任意类型。
get_json_object(string json_string, string path)
功能:解析JSON的字符串json_string,返回path指定的内容。如果输入的JSON字符串无效,那么返回NULL。path的具体语法如下:
举例:
假设表src_json中只有一个列json,里面的内容如下:
{"store":{"fruit":[{"weight":8,"type":"apple"},{"weight":9,"type":"pear"}],"egg":{"price":10,"color":"red"}},"email":"[email protected]","owner":"hzy"}
可以看到这是一个较为复杂的复合JSON字符串,我们可以使用百度出的在线JSON格式化工具将其格式化,如下:
{
"store": {
"fruit": [{
"weight": 8,
"type": "apple"
}, {
"weight": 9,
"type": "pear"
}],
"egg": {
"price": 10,
"color": "red"
}
},
"email": "[email protected]",
"owner": "hzy"
}
可以看出:第一层有三个字符串,key分别是:store,email,owner。value则是各自冒号后的内容。其中第一个JSON字符串中又嵌套了两层JSON字符串。
然后我们来使用get_json_object函数提取各项value:
提取单个JSON字符串的value,比如提取owner中的内容:
hive> SELECT get_json_object(json, '$.owner') FROM src_json;
hzy
提取嵌套JSON字符串里层的value,比如提取store中的egg的price:
hive> SELECT get_json_object(json, '$.store.egg.price') FROM src_json;
10
提取JSON字符串数组格式的value,比如提取store中的fruit中的第一个元素:
hive> SELECT get_json_object(json, '$.store.fruit[0]') FROM src_json;
{"weight":8,"type":"apple"}
如果在path中输入不存在的key,会返回NULL:
hive> SELECT get_json_object(json, '$.aaa') FROM src_json;
NULL
json_tuple(string jsonStr,stringk1,...,string kn)
功能:一次解析多个JSON字符串中的key-value,可以输入任意多个key,并返回其对应的value。
举例:
如果使用get_json_object想解析出email和owner需要写两次,如下:
hive (app)> SELECT get_json_object(json, '$.email') AS email
> ,get_json_object(json, '$.owner') AS owner
> FROM src_json;
email owner
[email protected] hzy
使用json_tuple则只需要使用一次,并且需要提取的key越多,这种方式越简便,如下:
有时最后结果除了要解析JSON还需要表中的其他字段,这时新定义的列别名注意不要和已有字段名重复
hive (app)> SELECT a.json
> ,b.email
> ,b.owner
> FROM src_json a lateral VIEW json_tuple(a.json, 'email', 'owner') b AS email,owner;
a.json b.email b.owner
{"store":{"fruit":[{"weight":8,"type":"apple"},{"weight":9,"type":"pear"}],"egg":{"price":10,"color":"red"}},"email":"[email protected]","owner":"hzy"} [email protected] hzy
hive (app)> SELECT email
> ,owner
> FROM src_json lateral VIEW json_tuple(json, 'email', 'owner') b AS email,owner;
email owner
[email protected] hzy
注意:使用lateral VIEW json_tuple后必须定义一个别名,否则会报错,如下:
hive (app)> SELECT email
> ,owner
> FROM src_json lateral VIEW json_tuple(json, 'email', 'owner') AS email,owner;
FAILED: ParseException line 3:63 Failed to recognize predicate 'AS'. Failed rule: 'identifier' in table alias
能看到这里的同学,就右上角点个赞吧,3Q~