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

时间:2019-02-13 19:23:39

标签: python aws-lambda amazon-sns amazon-athena aws-glue

我有一个上游应用程序将以下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” STRUCT中观察到,则我具有带空格的属性,例如“读取文件”和“转换文件”,当我尝试使用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)

但是,当我通过修改“ read_Files”和“ Convert_Files”之类的“ stageResults” STRUCT手动编辑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消息。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

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

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)