文章目录
- 一、分类总览
- 二、JSON基础
- 三、类型转换类
- [四、查询 / 提取类](#四、查询 / 提取类)
- 五、构造类
- [六、判断 / 属性类](#六、判断 / 属性类)
- 七、修改类
- [八、格式化 / 清洗类](#八、格式化 / 清洗类)
- 九、展开类
- 十、最容易混淆的函数对比
- 十一、常用案例
- 十二、使用限制
- 十三、参考资料
一、分类总览
1、函数分类
| 分类 | 主要解决的问题 | 代表函数 |
|---|---|---|
| 1、类型转换类 | JSON、STRING、ARRAY、MAP、STRUCT 之间互转 |
JSON_PARSE、JSON_FORMAT、FROM_JSON、TO_JSON |
| 2、查询 / 提取类 | 从 JSON 中读取单个值、多个字段或指定路径 | GET_JSON_OBJECT、JSON_EXTRACT、JSON_TUPLE |
| 3、构造类 | 构造 JSON ARRAY 或 JSON OBJECT |
JSON_ARRAY、JSON_OBJECT |
| 4、判断 / 属性类 | 判断合法性、路径存在性、包含关系、类型和长度 | JSON_VALID、JSON_EXISTS、JSON_CONTAINS、JSON_TYPE、JSON_LENGTH |
| 5、修改类 | 向 JSON 中插入或更新字段 | JSON_INSERT、JSON_SET |
| 6、格式化 / 清洗类 | 美化 JSON、移除 NULL、去除 JSON 字符串引号 | JSON_PRETTY、JSON_STRIP_NULLS、JSON_UNQUOTE |
| 7、展开类 | 将 JSON ARRAY / OBJECT 展开成多行 |
支持将JSON数组或JSON对象中的每个元素拆解(展开)成多行记录输出。 |
2、全部函数
| 分类 | 函数 | 功能 |
|---|---|---|
| 1、类型转换类 | JSON_PARSE |
将STRING类型转成JSON类型,非JSON格式转换为字符串会报错。 |
| 1、类型转换类 | JSON_FORMAT |
将JSON数据转换成STRING类型,默认不自动进行美化。 |
| 1、类型转换类 | FROM_JSON |
根据给定的JSON字符串和输出格式信息,返回ARRAY、MAP或STRUCT类型。 |
| 1、类型转换类 | TO_JSON |
将指定的复杂类型输出为JSON字符串。 |
| 2、查询 / 提取类 | GET_JSON_OBJECT |
在一个标准JSON字符串中,按照指定方式抽取指定的字符串。 |
| 2、查询 / 提取类 | JSON_EXTRACT |
按照指定的json_path,从JSON格式的字符串或JSON类型数据中提取对应的字符串或JSON数据。 |
| 2、查询 / 提取类 | JSON_TUPLE |
在一个标准的JSON字符串中,按照输入的一组键抽取各个键指定的字符串。 |
| 3、构造类 | JSON_ARRAY |
生成JSON ARRAY。将一个可能为空的JSON类型对象,转换为包含这些类型的数组。 |
| 3、构造类 | JSON_OBJECT |
生成JSON OBJECT,要求key和value成对出现。 |
| 4、判断 / 属性类 | JSON_VALID |
检查字符串是否为合法的JSON格式。 |
| 4、判断 / 属性类 | JSON_EXISTS |
查看json_path对应的JSON值是否存在。 |
| 4、判断 / 属性类 | JSON_CONTAINS |
判断一个JSON数据中是否包含指定的 JSON 元素。 |
| 4、判断 / 属性类 | JSON_TYPE |
返回JSON数据所属的数据类型名称。 |
| 4、判断 / 属性类 | JSON_LENGTH |
返回指定路径下的JSON数据的长度。 |
| 5、修改类 | JSON_INSERT |
在JSON文件指定位置中插入JSON值。 |
| 5、修改类 | JSON_SET |
替换JSON文件指定位置的值或新增对应的值。 |
| 6、格式化 / 清洗类 | JSON_PRETTY |
美化JSON,增加换行及空格。 |
| 6、格式化 / 清洗类 | JSON_STRIP_NULLS |
从JSON对象或JSON数组中移除所有值为null的字段或元素。 |
| 6、格式化 / 清洗类 | JSON_UNQUOTE |
去掉JSON数据中的引号。 |
| 7、展开类 | JSON_EXPLODE |
支持将JSON数组或JSON对象中的每个元素拆解(展开)成多行记录输出。 |
二、JSON基础
| 内容 | 说明 |
|---|---|
| JSON 类型 | MaxCompute 支持的复杂数据类型之一 |
JSON OBJECT |
Key-Value 结构 |
JSON ARRAY |
有序元素集合 |
| JSON Path | 用于定位 JSON 内部字段或元素 |
$.name |
获取根对象中的 name |
$.user.name |
获取嵌套对象中的字段 |
$[0] |
获取数组第一个元素 |
1、定义
MaxCompute 支持原生 JSON 数据类型。
常见 JSON:
json
{
"shop_id": "10001",
"shop_name": "北京朝阳店",
"platform": "美团",
"tags": ["核心店", "夜宵店"]
}
JSON 函数主要解决:
- STRING 与 JSON 类型转换;
- JSON 字段提取;
- JSON 构造;
- JSON 修改;
- JSON 格式判断;
- JSON 展开。
2、区别
JSON 与 ARRAY、MAP、STRUCT 的主要区别:
| 类型 | 特点 |
|---|---|
ARRAY |
同类元素按顺序存储 |
MAP |
Key-Value 结构,Key / Value 类型固定 |
STRUCT |
字段结构固定 |
JSON |
结构更灵活,可包含 Object、Array、String、Number、Boolean、Null |
MaxCompute 当前对 JSON 类型还有一些限制:
- JSON 类型不能直接用于比较。
- JSON 类型不能直接用于
ORDER BY、GROUP BY。 - JSON 类型不能直接作为
JOINKey。 - JSON 最多支持 20 层嵌套。
3、简单记忆
ARRAY= 同类型列表。
MAP= Key-Value。
STRUCT= 固定字段对象。
JSON= 更灵活的半结构化对象。
4、案例
sql
-- 结果:JSON 类型对象
SELECT JSON_PARSE('{"shop_id":"10001","shop_name":"北京朝阳店"}') AS json_data;
三、类型转换类
| 函数 | 功能 |
|---|---|
JSON_PARSE |
将STRING类型转成JSON类型,非JSON格式转换为字符串会报错。 |
JSON_FORMAT |
将JSON数据转换成STRING类型,默认不自动进行美化。 |
FROM_JSON |
根据给定的JSON字符串和输出格式信息,返回ARRAY、MAP或STRUCT类型。 |
TO_JSON |
将指定的复杂类型输出为JSON字符串。 |
1、定义
JSON_PARSE:把合法 JSON 格式的 STRING 转成原生 JSON 类型。JSON_FORMAT:把 JSON 类型转换回 STRING。FROM_JSON:把 JSON 字符串转换成明确的 ARRAY、MAP 或 STRUCT。TO_JSON:把ARRAY、MAP、STRUCT等复杂类型转换成 JSON 字符串。
2、区别
| 对比 | 区别 |
|---|---|
JSON_PARSE |
将STRING类型转成JSON类型,非JSON格式转换为字符串会报错。 |
JSON_FORMAT |
将JSON数据转换成STRING类型,默认不自动进行美化。 |
FROM_JSON |
根据给定的JSON字符串和输出格式信息,返回ARRAY、MAP或STRUCT类型。 |
TO_JSON |
将指定的复杂类型输出为JSON字符串。 |
最容易混淆的是:
JSON_PARSE / JSON_FORMAT针对 JSON 数据类型 。
FROM_JSON / TO_JSON更偏向 JSON 字符串与其他复杂类型互转。
3、简单记忆
PARSE= 字符串解析成 JSON。
FORMAT= JSON 格式化成字符串。
FROM_JSON= 从 JSON 字符串出来。
TO_JSON= 变成 JSON 字符串。
4、案例
sql
-- 结果:JSON 类型 {"a":1,"b":2}
SELECT JSON_PARSE('{"a":1,"b":2}') AS result;
-- 结果:{"a":1,"b":2}
SELECT JSON_FORMAT(JSON_PARSE('{"a":1,"b":2}')) AS result;
-- 结果:STRUCT<a:BIGINT,b:DOUBLE>
SELECT FROM_JSON('{"a":1,"b":0.8}', 'a BIGINT, b DOUBLE') AS result;
-- 结果:{"a":1,"b":2}
SELECT TO_JSON(NAMED_STRUCT('a', 1, 'b', 2)) AS result;
四、查询 / 提取类
| 函数 | 功能 |
|---|---|
GET_JSON_OBJECT |
在一个标准JSON字符串中,按照指定方式抽取指定的字符串。 |
JSON_EXTRACT |
按照指定的json_path,从JSON格式的字符串或JSON类型数据中提取对应的字符串或JSON数据。 |
JSON_TUPLE |
在一个标准的JSON字符串中,按照输入的一组键抽取各个键指定的字符串。 |
1、定义
GET_JSON_OBJECT:根据 JSON Path 从标准 JSON 字符串中提取指定内容。JSON_EXTRACT:根据 JSON Path 从 JSON 字符串或 JSON 类型数据中提取对应内容。JSON_TUPLE:根据多个 Key,一次性提取多个字符串。
2、区别
| 对比 | 区别 |
|---|---|
GET_JSON_OBJECT |
在一个标准JSON字符串中,按照指定方式抽取指定的字符串。 |
JSON_EXTRACT |
按照指定的json_path,从JSON格式的字符串或JSON类型数据中提取对应的字符串或JSON数据。 |
JSON_TUPLE |
在一个标准的JSON字符串中,按照输入的一组键抽取各个键指定的字符串。 |
使用选择:
只取一个字段:
GET_JSON_OBJECT / JSON_EXTRACT。一次取多个顶层字段:
JSON_TUPLE。已经使用原生 JSON 类型:优先考虑
JSON_EXTRACT。
3、简单记忆
GET_JSON_OBJECT= 取一个。
JSON_EXTRACT= 按 Path 抽取。
JSON_TUPLE= 一次取多个。
4、案例
sql
-- 结果:北京朝阳店
SELECT GET_JSON_OBJECT(
'{"shop_id":"10001","shop_name":"北京朝阳店"}',
'$.shop_name'
) AS result;
-- 结果:"北京朝阳店"
SELECT JSON_EXTRACT(
JSON_PARSE('{"shop_id":"10001","shop_name":"北京朝阳店"}'),
'$.shop_name'
) AS result;
-- 结果:10001,北京朝阳店
SELECT JSON_TUPLE(
'{"shop_id":"10001","shop_name":"北京朝阳店"}',
'shop_id',
'shop_name'
);
五、构造类
| 函数 | 功能 |
|---|---|
JSON_ARRAY |
生成JSON ARRAY。将一个可能为空的JSON类型对象,转换为包含这些类型的数组。 |
JSON_OBJECT |
生成JSON OBJECT,要求key和value成对出现。 |
1、定义
JSON_ARRAY:将多个输入值组合成一个JSON ARRAY。JSON_OBJECT:按照 Key、Value 成对传入,构造JSON OBJECT。
2、区别
| 函数 | 结果结构 |
|---|---|
JSON_ARRAY |
生成JSON ARRAY。将一个可能为空的JSON类型对象,转换为包含这些类型的数组。 |
JSON_OBJECT |
生成JSON OBJECT,要求key和value成对出现。 |
3、简单记忆
JSON_ARRAY= JSON 数组。
JSON_OBJECT= JSON 对象。
4、案例
sql
-- 结果:[1,"A",true]
SELECT JSON_ARRAY(1, 'A', true) AS result;
-- 结果:{"shop_id":"10001","shop_name":"北京朝阳店"}
SELECT JSON_OBJECT(
'shop_id', '10001',
'shop_name', '北京朝阳店'
) AS result;
六、判断 / 属性类
| 函数 | 功能 |
|---|---|
JSON_VALID |
检查字符串是否为合法的JSON格式。 |
JSON_EXISTS |
查看json_path对应的JSON值是否存在。 |
JSON_CONTAINS |
判断一个JSON数据中是否包含指定的 JSON 元素。 |
JSON_TYPE |
返回JSON数据所属的数据类型名称。 |
JSON_LENGTH |
返回指定路径下的JSON数据的长度。 |
1、定义
这一类不主要修改 JSON,而是判断 JSON 的状态或读取其属性。
2、区别
| 函数 | 判断 / 返回内容 |
|---|---|
JSON_VALID |
检查字符串是否为合法的JSON格式。 |
JSON_EXISTS |
查看json_path对应的JSON值是否存在。 |
JSON_CONTAINS |
判断一个JSON数据中是否包含指定的 JSON 元素。 |
JSON_TYPE |
返回JSON数据所属的数据类型名称。 |
JSON_LENGTH |
返回指定路径下的JSON数据的长度。 |
最容易混淆:
JSON_VALID判断"格式合法不合法"。
JSON_EXISTS判断"某个路径有没有"。
JSON_CONTAINS判断"某个值或结构包不包含"。
3、简单记忆
VALID= 合不合法。
EXISTS= 有没有路径。
CONTAINS= 包不包含。
TYPE= 什么类型。
LENGTH= 有多少项。
4、案例
sql
-- 结果:true
SELECT JSON_VALID('{"a":1,"b":2}') AS result;
-- 结果:true
SELECT JSON_EXISTS(
JSON_PARSE('{"user":{"name":"Alice"}}'),
'$.user.name'
) AS result;
-- 结果:true
SELECT JSON_CONTAINS(
JSON_PARSE('{"a":1,"b":2}'),
JSON_PARSE('1'),
'$.a'
) AS result;
-- 结果:OBJECT
SELECT JSON_TYPE(
JSON_PARSE('{"a":1}')
) AS result;
-- 结果:3
SELECT JSON_LENGTH(
JSON_PARSE('[1,2,3]')
) AS result;
七、修改类
| 函数 | 功能 |
|---|---|
JSON_INSERT |
在JSON文件指定位置中插入JSON值。 |
JSON_SET |
替换JSON文件指定位置的值或新增对应的值。 |
1、定义
JSON_INSERT:向指定 JSON Path 插入值,如果目标位置已经存在,则不会覆盖。JSON_SET:目标位置存在时更新,不存在时新增。
2、区别
假设:
json
{"name":"Alice"}
对 $.name 写入 "Bob":
| 函数 | 结果 |
|---|---|
JSON_INSERT |
在JSON文件指定位置中插入JSON值。 |
JSON_SET |
替换JSON文件指定位置的值或新增对应的值。 |
对不存在的 $.age 写入 30:
| 函数 | 结果 |
|---|---|
JSON_INSERT |
在JSON文件指定位置中插入JSON值。 |
JSON_SET |
替换JSON文件指定位置的值或新增对应的值。 |
3、简单记忆
INSERT= 只插入,不覆盖。
SET= 有就改,没有就加。
4、案例
sql
-- 结果:{"name":"Alice","age":30}
SELECT JSON_INSERT(
JSON_PARSE('{"name":"Alice"}'),
'$.age',
30
) AS result;
-- 结果:{"name":"Bob"}
SELECT JSON_SET(
JSON_PARSE('{"name":"Alice"}'),
'$.name',
'Bob'
) AS result;
八、格式化 / 清洗类
| 函数 | 功能 |
|---|---|
JSON_PRETTY |
美化JSON,增加换行及空格。 |
JSON_STRIP_NULLS |
从JSON对象或JSON数组中移除所有值为null的字段或元素。 |
JSON_UNQUOTE |
去掉JSON数据中的引号。 |
1、定义
JSON_PRETTY:给 JSON 添加换行和缩进,提高可读性。JSON_STRIP_NULLS:从JSON OBJECT或 ARRAY 中删除值为null的字段或元素。JSON_UNQUOTE:去除JSON STRING外层引号,返回普通字符串内容。
2、区别
| 函数 | 用途 |
|---|---|
JSON_PRETTY |
美化JSON,增加换行及空格。 |
JSON_STRIP_NULLS |
从JSON对象或JSON数组中移除所有值为null的字段或元素。 |
JSON_UNQUOTE |
去掉JSON数据中的引号。 |
3、简单记忆
PRETTY= 变好看。
STRIP_NULLS= 去 NULL。
UNQUOTE= 去引号。
4、案例
sql
-- 结果:增加换行和缩进后的 JSON
SELECT JSON_PRETTY(
JSON_PARSE('{"a":1,"b":{"c":2}}')
) AS result;
-- 结果:{"a":1}
SELECT JSON_STRIP_NULLS(
JSON_PARSE('{"a":1,"b":null}')
) AS result;
-- 结果:北京朝阳店
SELECT JSON_UNQUOTE(
JSON_PARSE('"北京朝阳店"')
) AS result;
九、展开类
| 函数 | 功能 |
|---|---|
JSON_EXPLODE |
支持将JSON数组或JSON对象中的每个元素拆解(展开)成多行记录输出。 |
1、定义
JSON_EXPLODE 用于把 JSON ARRAY 或 JSON OBJECT 中的元素展开成多行记录。
它适合把半结构化 JSON 转换成后续 SQL 更容易处理的明细行。
2、区别
与 EXPLODE 的区别:
| 函数 | 主要输入 |
|---|---|
EXPLODE |
ARRAY / MAP |
JSON_EXPLODE |
支持将JSON数组或JSON对象中的每个元素拆解(展开)成多行记录输出。 |
因此:
已经是 MaxCompute ARRAY / MAP:使用
EXPLODE。数据还是 JSON 类型:使用
JSON_EXPLODE。
3、简单记忆
JSON_EXPLODE= 把 JSON "炸开"成多行。
4、案例
sql
-- 结果:JSON数组中的 1、2、3 分别展开为多行
SELECT JSON_EXPLODE(
JSON_PARSE('[1,2,3]')
);
十、最容易混淆的函数对比
| 函数组合 | 最核心区别 |
|---|---|
JSON_PARSE vs JSON_FORMAT |
STRING→JSON vs JSON→STRING |
FROM_JSON vs JSON_PARSE |
JSON STRING→ARRAY/MAP/STRUCT vs STRING→原生 JSON |
TO_JSON vs JSON_FORMAT |
复杂类型→JSON STRING vs 原生 JSON→STRING |
GET_JSON_OBJECT vs JSON_EXTRACT |
偏字符串提取 vs 原生 JSON Path 提取 |
GET_JSON_OBJECT vs JSON_TUPLE |
单 Path vs 多 Key |
JSON_EXTRACT vs JSON_TUPLE |
单 Path 提取 vs 一次提取多个顶层 Key |
JSON_ARRAY vs JSON_OBJECT |
构造数组 vs 构造对象 |
JSON_VALID vs JSON_EXISTS |
JSON 是否合法 vs 指定 Path 是否存在 |
JSON_EXISTS vs JSON_CONTAINS |
判断 Path vs 判断是否包含某 JSON 内容 |
JSON_INSERT vs JSON_SET |
只新增、不覆盖 vs 更新或新增 |
JSON_PRETTY vs JSON_FORMAT |
美化展示 vs 普通 JSON→STRING |
JSON_STRIP_NULLS vs JSON_UNQUOTE |
删除 null vs 去掉 JSON 字符串引号 |
JSON_LENGTH vs JSON_TYPE |
返回元素 / 成员数量 vs 返回数据类型 |
JSON_EXPLODE vs EXPLODE |
展开 JSON vs 展开 ARRAY / MAP |
十一、常用案例
1、判断字符串是不是合法JSON
sql
-- 结果:true
SELECT JSON_VALID('{"shop_id":"10001","platform":"美团"}') AS is_valid;
2、提取单个字段
sql
-- 结果:10001
SELECT GET_JSON_OBJECT(
'{"shop_id":"10001","platform":"美团"}',
'$.shop_id'
) AS shop_id;
3、一次提取多个字段
sql
-- 结果:10001,美团
SELECT JSON_TUPLE(
'{"shop_id":"10001","platform":"美团"}',
'shop_id',
'platform'
);
4、提取嵌套字段
sql
-- 结果:北京
SELECT JSON_UNQUOTE(
JSON_EXTRACT(
JSON_PARSE('{"shop":{"city":"北京","name":"朝阳店"}}'),
'$.shop.city'
)
) AS city;
5、构造JSON对象
sql
-- 结果:{"shop_id":"10001","platform":"美团"}
SELECT JSON_OBJECT(
'shop_id', '10001',
'platform', '美团'
) AS shop_json;
6、新增JSON字段
sql
-- 结果:{"shop_id":"10001","platform":"美团"}
SELECT JSON_SET(
JSON_PARSE('{"shop_id":"10001"}'),
'$.platform',
'美团'
) AS result;
7、删除JSON中的NULL
sql
-- 结果:{"shop_id":"10001","platform":"美团"}
SELECT JSON_STRIP_NULLS(
JSON_PARSE(
'{"shop_id":"10001","platform":"美团","remark":null}'
)
) AS result;
8、JSON转STRUCT
sql
-- 结果:STRUCT<shop_id:STRING,platform:STRING>
SELECT FROM_JSON(
'{"shop_id":"10001","platform":"美团"}',
'shop_id STRING, platform STRING'
) AS shop_info;
十二、使用限制
1、定义
MaxCompute 原生 JSON 类型当前存在一定使用限制,实际建模前需要关注。
2、区别
主要限制:
- 暂不支持给已有表新增 JSON 列。
- 暂不支持 Cluster 表。
- 暂不支持 Delta Table 类型表。
- JSON 类型暂不支持直接比较。
- JSON 类型暂不支持
ORDER BY。 - JSON 类型暂不支持
GROUP BY。 - JSON 类型暂不支持作为
JOINKey。 JSON NUMBER整数部分使用BIGINT存储,超出BIGINT范围可能溢出。JSON NUMBER小数部分使用DOUBLE存储,可能存在精度损失。- 不支持 Unicode
\u0000。 - JSON 类型最多支持 20 层嵌套。
- Java UDF、Python UDF 暂不支持 JSON 类型。
- 如果数据还需要被 Hologres 等其他引擎读取,需要先确认兼容性。
3、简单记忆
JSON 灵活,但原生 JSON 类型在排序、分组、
JOIN、外部引擎兼容方面限制更多。如果只是简单字段提取,有时保留 STRING 再通过 JSON 函数解析会更灵活。
4、案例
sql
-- 推荐:先判断 JSON 合法性,再进行解析
SELECT
CASE
WHEN JSON_VALID(json_str)
THEN JSON_PARSE(json_str)
ELSE NULL
END AS json_data
FROM source_table;
十三、参考资料
阿里云 MaxCompute 官方文档: