项目目标
本教程将指导您使用阿里云 Data Lake Analytics(DLA)直接分析存储在 OSS 中的连续 JSON 数据对象。所有 JSON 对象连续存放在同一行,无需编写 UDF 或自定义 Hive TextInputFormat,仅需三步即可完成查询。
最终效果
完成本教程后,您将能够对如下格式的 JSON 数据文件进行查询:
{"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}{"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}{"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}{"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}
每一行由多个独立 JSON 对象首尾相连构成,未使用换行或分隔符。
技术方案
利用 DLA 内置的 JsonSingleLineInputFormat 将整行内容读取为单列字符串,再通过 wrap_ifnotexist 函数补全可能导致解析失败的缺失括号,最后使用标准 JSON 函数进行解析和查询。
环境与依赖
- 阿里云 OSS 存储桶,用于存放 JSON 数据文件
- 阿里云 Data Lake Analytics 服务(已开通)
- DLA 控制台或 DLA SQL 执行环境
项目结构
本例中数据文件位于 OSS 路径:oss://your_bucket/json_data/。DLA 中仅创建一张外部表,无需额外目录或文件。
核心实现
第一步:JSON 数据上传到阿里云 OSS
将连续的 JSON 数据文件上传到您的 OSS 存储桶中。对于云上日志链路,可使用 Logtail 等工具将 JSON 日志投递到 OSS。更多细节可参考 云原生日志数据分析上手指南 中的 JSON 部分。
第二步:在 DLA 中创建外部表
在 DLA 中执行以下建表语句,指定输入格式为 com.alibaba.cloud.dla.inputformat.JsonSingleLineInputFormat,将整行内容映射为单列 STRING 类型:
CREATE EXTERNAL TABLE single_line_json (
data STRING
)
STORED AS INPUTFORMAT 'com.alibaba.cloud.dla.inputformat.JsonSingleLineInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 'oss://your_bucket/json_data/';
注意:LOCATION 需替换为您的实际 OSS 路径。若数据文件使用分区存储,可参考上述指南中的分区模式建表方法。
第三步:使用 DLA 函数处理 JSON 数据
由于每行数据由多个 JSON 对象连续拼接而成,但 JsonSingleLineInputFormat 将整行作为一个字符串读入,该字符串本身并非合法的 JSON 格式(缺少外层包裹)。使用 wrap_ifnotexist 函数为字符串首尾添加大括号,使其成为合法 JSON:
SELECT json_parse(wrap_ifnotexist(data, '{', '}')) AS a
FROM single_line_json;
其中 json_parse 是 DLA 提供的 JSON 解析函数,可将字符串解析为 JSON 对象。更多 DLA JSON 函数请参考 官方文档。关于 JSON 数组处理可参考 DLA 新增函数的 JSON 数组处理部分。云上最便捷的 JSON 数据处理方法可参考 这篇文章。
运行方法
- 在 DLA 控制台打开 SQL 编辑器。
- 执行建表语句(第二步)。
- 执行查询语句(第三步)。
查询结果示例:
-----------------------------------------------------------------------------------------------------------------------------------------------
| a
-----------------------------------------------------------------------------------------------------------------------------------------------
| {"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}
| {"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}
| {"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}
| {"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"},{"firstName":"Thomas","lastName":"Carter"}]}
-----------------------------------------------------------------------------------------------------------------------------------------------
此时每一行都是一个完整的 JSON 对象,可在此基础上使用 json_extract、json_array_get 等函数进行更细粒度的查询。
结果验证
- 确认表
single_line_json已创建成功,且LOCATION指向正确的 OSS 路径。 - 确认查询能返回预期数量的行,且每行
a列值为合法 JSON 字符串。 - 尝试使用
SELECT json_extract(a, '$.employees[0].firstName') FROM single_line_json;验证能提取到Bill。
常见问题
- 建表失败:检查 OSS 路径是否正确,DLA 是否有权限访问该 OSS 路径。
- 查询结果为空:确认数据文件确实位于指定路径,文件内容格式符合预期(整行为连续 JSON 对象)。
- JSON 解析报错:确保每行数据本身不含多余换行或空格,若数据本身已包含外层大括号,则无需使用
wrap_ifnotexist,可直接使用json_parse。
后续优化
- 对于海量数据,建议使用分区表提升查询性能,参考 云原生日志数据分析上手指南 中的分区建表方法。
- 可使用 DLA 提供的其他 JSON 函数处理嵌套数组或复杂结构。
- 如有特殊 JSON 存储格式需求,可在阿里云 DLA 产品页面提工单,官方将提供快速支持。
