求助:使用Python在AWS S3中合并JSON文件,解决内容覆盖问题
解决S3中合并两个JSON文件避免覆盖的问题
我明白你现在碰到的问题了——想要把S3桶里的patienta.json和patient_b.json两个文件的内容合并成单个patient.json,但之前的代码会直接覆盖目标文件内容,根本达不到合并的效果对吧?别着急,我给你整理了完整的解决方案,包括调整后的代码和关键说明:
核心思路
要实现合并而不是覆盖,关键得先把两个源文件的内容都读出来,合并成一个新的JSON结构之后,再上传到S3的patient.json里(毕竟S3是对象存储,上传同名文件本身就是覆盖,但我们上传的是合并后的完整内容,就不会丢失任何数据了)。
完整Lambda代码
#!/usr/bin/python # -*- coding: utf-8 -*- import boto3 import json from decimal import Decimal # 处理Decimal类型的JSON编码器(如果你的JSON数据来自DynamoDB这类服务,大概率需要这个) class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Decimal): # 把Decimal转成整数或浮点数,避免序列化报错 return int(o) if o % 1 == 0 else float(o) return super().default(o) s3_client = boto3.client('s3') def lambda_handler(event, context): # 从触发事件里获取S3桶名称 bucket = event['Records'][0]['s3']['bucket']['name'] # 定义要处理的源文件和目标文件名 source_files = ['patienta.json', 'patient_b.json'] target_file = 'patient.json' # 用来存储合并后的数据,这里默认用数组格式,你可以按需调整 merged_data = [] # 逐个读取并处理源文件 for file_name in source_files: try: # 从S3获取文件内容 response = s3_client.get_object(Bucket=bucket, Key=file_name) # 读取并解析JSON数据 file_content = response['Body'].read().decode('utf-8') json_data = json.loads(file_content, parse_float=Decimal, parse_int=Decimal) # 根据源文件的JSON结构做合并: # 如果是单个患者对象,就添加到数组;如果已经是数组,就直接合并数组 if isinstance(json_data, dict): merged_data.append(json_data) elif isinstance(json_data, list): merged_data.extend(json_data) except s3_client.exceptions.NoSuchKey: # 处理文件不存在的情况,避免整个函数崩溃 print(f"警告:桶 {bucket} 里找不到文件 {file_name}") continue # 把合并后的数据转成JSON字符串 merged_json = json.dumps(merged_data, cls=DecimalEncoder) # 上传合并后的内容到目标文件 s3_client.put_object( Bucket=bucket, Key=target_file, Body=merged_json, ContentType='application/json' ) return { 'statusCode': 200, 'body': json.dumps(f"搞定!已经合并两个文件并上传到 {target_file}") }
关键细节说明
- Decimal编码器:如果你的JSON数据是从DynamoDB导出的,里面会有Decimal类型的数据,这个编码器能帮你把它转成普通的数字类型,避免JSON序列化失败。如果你的数据里没有这种类型,可以直接删掉这个类,以及
json.dumps里的cls=DecimalEncoder参数。 - 合并逻辑自定义:上面的代码默认把两个文件的内容放到一个数组里(比如两个患者对象变成一个患者列表)。如果你想把两个对象的属性合并成一个对象(比如把两个文件里的字段整合到同一个患者对象里),可以把合并部分改成这样:
merged_data = {} for file_name in source_files: # ...读取解析代码不变... if isinstance(json_data, dict): merged_data.update(json_data) - 权限注意事项:别忘了给你的Lambda执行角色加上
S3:GetObject和S3:PutObject的权限,不然会出现权限不足的报错。 - 容错处理:代码里加了文件不存在的捕获,就算其中一个源文件丢了,另一个文件的内容也能正常合并进去,不会直接崩溃。
内容的提问来源于stack exchange,提问作者Anand
相关产品推荐
相关产品推荐

