使用 AWS Lambda 从 AWS SNS 读取时修改 JSON 消息

Posted

技术标签:

【中文标题】使用 AWS Lambda 从 AWS SNS 读取时修改 JSON 消息【英文标题】:Modify JSON message while reading from AWS SNS using AWS Lambda 【发布时间】:2019-02-13 19:23:38 【问题描述】:

我有一个上游应用程序将以下 JSON 消息发送到 SNS 主题。我们使用 AWS lambda 函数将这个 JSON 对象保存在 S3 中:


"processResult": 
    "processName": "XYZ",
    "stageResults": 
        "Read Files": 
            "status": "PROCESSED",
            "error": "",
            "timeTaken": 26064469473
        ,
        "Convert Files": 
            "status": "PROCESSED",
            "error": "",
            "timeTaken": 97968896
        
    ,
    "processMetrics": 
        "filesProcessed": 1157,
        "filesWithExceptionCount": 1,
        "timeTaken": "367.460031s",
        "metricsCalcTime": "6.061847s",
        "totalTimeTaken": "373.521878s"
    ,
    "succeeded": true
  

如果您在“stageResults”结构中观察到,我有带空格的属性,例如“读取文件”和“转换文件”,当我尝试使用 AWS Athena(AWS Glue Crawler)从 S3 读取此 JSON 时,我收到以下错误:

    HIVE_METASTORE_ERROR: com.facebook.presto.spi.PrestoException: Error: : expected at the position 51 of 'struct<....
......but ' ' is found. (Service: null; Status Code: 0; Error Code: null; Request ID: null)

但是当我通过修改“stageResults”STRUCT(如“Read_Files”和“Convert_Files”)手动编辑 JSON 消息时,我能够使用 AWS Athena 表成功读取和查询 JSON。

以下是 AWS Lambda 中的一段代码,它触发 SNS 主题,读取 JSON 消息并将其保存在 S3 中:

import json
import boto3
import random
import string

file_name = ''.join([random.choice(string.ascii_lowercase) for i in range(16)])

def lambda_handler(event, context):
    target_bucket = 'bucket-name'
    target_key = 'input=clientdata/'  + file_name + '.json'
    s3 = boto3.resource('s3')
    for record in event['Records']:
        payload = record["body"]
        data = json.loads(payload)
        print(data)
        print("copying JSON message...")
        s3.Object('target_bucket', 'target_key').put(
            Body=(bytes(json.dumps(data).encode('UTF-8')))
        )

现在,我想知道如何在使用 AWS Lambda 将其保存到 S3 之前修改此 JSON 消息。任何帮助表示赞赏。

【问题讨论】:

由于您的问题归结为更改字典键的名称,我建议您查看this 没错,但我不知道我会收到什么密钥。我需要做的就是在保存之前删除字典键中的空格。 【参考方案1】:

如果您只想将包含空格的每个键更改为适合您需要的内容,则可以这样做:

import re
wrong_keys = []
for key in data.keys():
    if key.strip().find(" ") != -1:
        wrong_keys.append(key)
for key in wrong_key:
  data[re.sub(r'[\W]+', '_',key)] = data.pop(key)

【讨论】:

以上是关于使用 AWS Lambda 从 AWS SNS 读取时修改 JSON 消息的主要内容,如果未能解决你的问题,请参考以下文章

AWS SNS子脚本与lambda函数的触发器?

AWS lambda 发送 SNS“成功”但未实际发送消息

AWS - 在 SNS 订阅或 Lambda 函数上设置死信队列有啥区别?

如何使用AWS Lambda和SNS事件触发Spring Cloud功能的重试

AWS Beanstalk - 创建新环境时向 Lambda 发送 SNS 通知

使用 AWS Lambda 观看 SNS 主题并通过 websocket 交付?