如何通过忽略 boto3 中的空元素将 JSON 数据写入 Dynamodb

问题描述 投票:0回答:2

我想将以下数据组写入Dynamodb。
大约有100条数据。由于图像不一定是必需的,因此存在带有和不带有 image_url 元素的混合。

(问题列表.json)

{
  "q_id" : "001",
  "q_body" : "Where is the capital of the United States?",
  "q_answer" : "Washington, D.C.",
  "image_url" : "/Washington.jpg",
  "keywords" : [
    "UnitedStates",
    "Washington"
  ]
},
{
  "q_id" : "002",
  "q_body" : "Where is the capital city of the UK?",
  "q_answer" : "London",
  "image_url" : "",
  "keywords" : [
    "UK",
    "London"
  ]
},

由于是写入测试阶段,因此要写入的 Dynamodb 是使用 Serverless 框架的 serverless-dynamodb-local 插件在 localhost:8000 中准备的,而不是生产环境。
为了将上述 JSON 数据写入此 Dynamodb,我在 Boto 3(适用于 Python 的 AWS SDK)中编写了以下代码。

from __future__ import print_function
import boto3
import codecs
import json

dynamodb = boto3.resource('dynamodb', region_name='us-east-1', endpoint_url="http://localhost:8000")

table = dynamodb.Table('questionListTable')

with open("questionList.json", "r", encoding='utf-8') as json_file:
    items = json.load(json_file)
    for item in items:
        q_id = item['q_id']
        q_body = item['q_body']
        q_answer = item['q_answer']
        image_url = item['image_url']
        keywords = item['keywords']

        print("Adding detail:", q_id, q_body)

        table.put_item(
            Item={
                'q_id': q_id,
                'q_body': q_body,
                'q_answer': q_answer,
                'image_url': image_url,
                'keywords': keywords,
            }
        )

执行此代码时,空字符部分出现以下错误。

botocore.exceptions.ClientError:调用 PutItem 操作时发生错误 (ValidationException):一个或多个参数值无效:AttributeValue 不得包含空字符串

显然这似乎是由 JSON 的 null 字符引起的。
如果将包含空字符的image_url从写入目标中排除,如下所示,则写入完成,没有任何问题。

from __future__ import print_function
import boto3
import codecs
import json

dynamodb = boto3.resource('dynamodb', region_name='us-east-1', endpoint_url="http://localhost:8000")

table = dynamodb.Table('questionListTable')

with open("questionList.json", "r", encoding='utf-8') as json_file:
    items = json.load(json_file)
    for item in items:
        q_id = item['q_id']
        q_body = item['q_body']
        q_answer = item['q_answer']
        #image_url = item['image_url']
        keywords = item['keywords']

        print("Adding detail:", q_id, q_body)

        table.put_item(
            Item={
                'q_id': q_id,
                'q_body': q_body,
                'q_answer': q_answer,
                #'image_url': image_url,
                'keywords': keywords,
            }
        )

由于DynamoDB是NoSQL,可能还有其他方法可以很好地利用其特性,但是如何正确编写代码以忽略空字符来编写上述数据呢?我想说“如果image_url存在,就写它,如果不存在,忽略它。”

谢谢你。

python json amazon-web-services amazon-dynamodb boto3
2个回答
5
投票

我解决了我的问题。您可以按如下方式设置 null。

from __future__ import print_function
import boto3
import codecs
import json

dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-1', endpoint_url="http://localhost:8000")

table = dynamodb.Table('questionListTable')

with open("questionList.json", "r", encoding='utf-8_sig') as json_file:
    items = json.load(json_file)
    for item in items:
        q_id = item['q_id']
        q_body = item['q_body']
        q_answer = item['q_answer']
        image_url = item['image_url'] if item['image_url'] else None
        keywords = item['keywords'] if item['keywords'] else None

    print("Adding detail:", q_id, q_body)

    table.put_item(
        Item={
            'q_id': q_id,
            'q_body': q_body,
            'q_answer': q_answer,
            'image_url': image_url,
            'keywords': keywords,
        }
    )

为了检查Dynamodb的情况,使用Serverless框架的离线插件在本地环境中运行API Gateway。当我实际使用 Postman 调用 API 时,Null 已正确插入到值中。

{
  "q_id" : "001",
  "q_body" : "Where is the capital of the United States?",
  "q_answer" : "Washington, D.C.",
  "image_url" : "/Washington.jpg",
  "keywords" : [
    "UnitedStates",
    "Washington"
  ]
},
{
  "q_id" : "002",
  "q_body" : "Where is the capital city of the UK?",
  "q_answer" : "London",
  "image_url" : "null",
  "keywords" : [
    "UK",
    "London"
  ]
},

0
投票

@uhiyama 您的解决方案中的以下代码行可以使用 get() 方法进行总结/简化:

image_url = item['image_url'] if item['image_url'] else None
image_url = item.get("image_url")
© www.soinside.com 2019 - 2024. All rights reserved.