Hive SQL如何从json格式的字符串中提取出所有key字段


=Start=

缘由:

在用Hive SQL做数据分析的过程中遇到的一个情况,觉得挺典型的,后面可能会遇到,所以记录下来,方便后面参考。

正文:

参考解答:

测试样例

# file_schema (类型1,string类型的列名列表,用方括号包裹起来,不需要额外处理)
["企业号uid","公司名称"]

# file_schema (类型2,string类型字段,json字符串格式,需要将所有的key都提取出来)
{"activity_type":"string","business_tag":"string","activity_tags":"string","campaign_type":"string","tool_name":"string"}


-- 提取结果
# file_columns1
activity_type,business_tag,activity_tags,campaign_type,tool_name

# file_columns2
"activity_type","business_tag","activity_tags","campaign_type","tool_name"

# file_columns3
{"activity_type","business_tag","activity_tags","campaign_type","tool_name"}

# file_columns4
"activity_type","business_tag","activity_tags","campaign_type","tool_name"

-- 提取方法(为了显示清楚使用case-when语法,其实可以用单行的if()函数来达到目标)
file_schema,
case
when file_schema like '{%' then concat_ws(',',map_keys(str_to_map(replace(substr(file_schema,2),'"',''))))
else file_schema
end as file_columns1,
case
when file_schema like '{%' then concat_ws(',',map_keys(str_to_map(substr(file_schema,2))))
else file_schema
end as file_columns2,
case
when file_schema like '{%' then regexp_replace(file_schema,':"(bigint|tinyint|smallint|int|string|varchar|char|float|double|boolean|decimal|timestamp)"','')
else file_schema
end as file_columns3,
regexp_replace(concat_ws(',',map_keys(str_to_map(regexp_replace(file_schema,'\\([a-zA-Z0-9]+,[a-zA-Z0-9]+\\)','')))),'\\{','') AS file_columns4,

str_to_map(字符串参数, 分隔符1, 分隔符2)
使用两个分隔符将文本拆分为键值对。
分隔符1将文本分成K-V对,分隔符2分割每个K-V对。对于分隔符1默认分隔符是 ',',对于分隔符2默认分隔符是 ':'

> select str_to_map("name:zhangsan,age:25") as m1
{"age":"25","name":"zhangsan"}

> desc function str_to_map;
Function: str_to_map
Class: org.apache.spark.sql.catalyst.expressions.StringToMap
Usage: str_to_map(text[, pairDelim[, keyValueDelim]]) - Creates a map after splitting the text into key/value pairs using delimiters. Default delimiters are ',' for `pairDelim` and ':' for `keyValueDelim`. Both `pairDelim` and `keyValueDelim` are treated as regular expressions.


> select cast(str_to_map("A:1,B:1,C:1") as map<string, int>)
-- {'A': 1, 'B': 1, 'C': 1}

相关解释

下载文件列名(file_schema)字段的分析:

  1. 只有在下载格式为Excel的时候,才会是下面这种格式:
    {"column1":"bigint","column2":"int","column3":"double"}
  2. 其它的情况下,就是单纯的列名格式(已完全满足需求,不用额外处理):
    ["column1","column2","column3","column4"]

Hive SQL中的一些函数功能、使用场景学习

str_to_map函数的第一个参数字符串是不以括号包裹的,就是单纯的:
key1:value1,key2:value2
这种形式。

当前碰到的一个字符串是:
{"column1":"double","column2":"int","column3":"double"}
这种形式。

方法一(更直接)

分析了一下,value的取值范围绝大部分是Hive支持的原始数据类型(数值型,Boolean,字符串,时间戳),所以有一种方式就是把这些相对固定(可以枚举出来)的内容进行批量替换,就可以达到我的目标——只保留键名key列表:

if(file_schema like '{%' , regexp_replace(file_schema,':"(bigint|tinyint|smallint|int|string|varchar|char|float|double|boolean|decimal|timestamp)"','') , file_schema) as file_columns
方法二(更通用)

上面这种情况比较特殊——value的取值是可以枚举出来,有相对固定范围的。除此之外,对于value取值无法预估的情况下,可以使用另一个更为通用的方法

  1. 在简单把字符串处理之后,用 str_to_map 函数将字符串转换成map类型
  2. 然后使用 map_keys 函数取出键名key列表
  3. 再用 concat_ws 将array类型转换成string类型即可
  4. (可选)使用 replace/regexp_replace 函数对字符串做一些格式化处理
if(file_schema like '{%' , concat_ws(',',map_keys(str_to_map(replace(substr(file_schema,2),'"','')))) , file_schema) as file_columns
参考链接:

Hive Tutorial
https://cwiki.apache.org/confluence/display/Hive/Tutorial

Hive str_to_map函数
https://www.cnblogs.com/kopao/p/13753560.html

大数据之Hive:Hive函数之str_to_map函数
https://blog.csdn.net/weixin_43597208/article/details/117450579

str_to_map returns map. How to make it return map?
https://stackoverflow.com/questions/38537382/str-to-map-returns-mapstring-string-how-to-make-it-return-mapstring-int

str_to_map function
https://docs.databricks.com/en/sql/language-manual/functions/str_to_map.html

Hive 中 map 类型字段的常用方法学习
https://ixyzero.com/blog/archives/5733.html

hive解析不确定key的json,将key和value分别放入两列
https://blog.csdn.net/lz6363/article/details/103910313

Hive 从json中提取出所有key
https://www.cnblogs.com/144823836yj/p/14752548.html

=END=


《“Hive SQL如何从json格式的字符串中提取出所有key字段”》 有 1 条评论

  1. Hive–map/string→json&处理Json数据的函数
    https://blog.csdn.net/qq_46893497/article/details/109959763
    `
    hive中转化json 格式的函数

    1. string 类型 json
    * named_struct: 生成key和value的struct结构,传递参数为 named_struct(key1,value1,key2,value2, …, keyN,valueN)
    * to_json: 将各种复杂结构(例如:LIST,MAP,NAMED_STRUCT 等)转换成json格式

    2. map类型 json
    * str_to_map 可以先将string切割成map,再转json
    * to_json: 将各种复杂结构(例如:LIST,MAP,NAMED_STRUCT 等)转换成json格式

    Hive中处理json数据的两种方式

    第一种:将json数据作为字符串进行处理
    * get_json_object – 一次取一个字段
    * json_tuple – 一次取多个字段

    第二种:通过专门的解析类直接加载一个json格式的数据到Hive中
    `

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注