Kinesis Firehose写入S3的JSON对象缺失分隔逗号问题排查
我刚碰到过几乎一模一样的坑!咱们来一步步弄明白问题出在哪,以及怎么修复:
问题根源分析
你当前的API Gateway模板是把data数组里的每个元素单独包装成一个Firehose Record发送的。而Kinesis Firehose的默认行为是:收到多个Record时,会直接把每个Record解码后的内容按顺序拼接写入S3,不会自动添加逗号、换行或者任何分隔符。这就导致原本的数组被拆成了独立的JSON对象直接连在一起,变成了{...}{...}这种不合法的JSON结构。
快速修复方案:把整个数组作为单个Record发送
最简单的解决方式是修改API Gateway的映射模板,把整个data数组作为一个完整的JSON字符串,打包成一个Firehose Record发送。这样Firehose写入S3的就是完整的合法JSON数组了。
修改后的模板如下:
#set($root = $input.path('$')) { "DeliveryStreamName": "some-delivery-stream", "Records": [ { "Data": "$util.base64Encode($input.json('$.data'))" } ] }
这个模板直接提取请求里的data数组(已经是合法的JSON数组格式),base64编码后作为单个Record的Data字段发送给Firehose。Firehose解码后写入S3的内容就会是你最初期望的[{"key1": value1, "key2": value2}, {"key1": value1, "key2": value2}]格式。
进阶方案:保留单个Record并输出合法格式(JSON Lines)
如果你因为业务需要,必须把每个数组元素作为单独的Firehose Record发送(比如后续要对单个记录做处理),可以配置Firehose的输出格式转换,让它输出JSON Lines格式(每个JSON对象单独占一行),这种格式也是大部分数据处理工具(比如Spark、Pandas)支持的。
具体配置步骤:
- 进入Kinesis Firehose控制台,找到你的Delivery Stream
- 编辑“Destination settings”,开启“Record format conversion”
- 在“Output format”里选择“JSON”,并确保“Record delimiter”设置为“Newline”(默认就是这个)
这样Firehose会把每个Record的内容单独放在一行,S3里的文件内容就会变成:
{"key1": value1, "key2": value2} {"key1": value1, "key2": value2}
这种格式虽然不是数组,但每行都是独立的合法JSON对象,同样可以被正常解析处理。
内容的提问来源于stack exchange,提问作者sjishan

