'Error when doing a PUTITEM type: <class 'str'>, valid types: <class 'dict'>
When doing a putitem to dynamo it is giving me the following error, the json I am reading from s3. this is the code
dictItems = json.load(object_summary.get()['Body'])
item2 = {
"ruc" : dictItems['ruc'],
"dni" :dictItems['dni'],
"number_operation" :dictItems['number_operation'],
"name" :dictItems['name'],
"address" :dictItems['address'],
"validation_date" :dictItems['validation_date'],
"directory" :dictItems['directory'],
"addresses" :dictItems['addresses'],
"representatives" :dictItems['representatives'],
"sunat" :dictItems['sunat'],
"debt" :dictItems['debt'],
"bad_debtor_portfolio" :dictItems['bad_debtor_portfolio'],
"foreign_trade" :dictItems['foreign_trade'],
"legal_information" :dictItems['legal_information'],
"query_indicator" :dictItems['query_indicator'],
"claim_review": dictItems['claim_review']
}
dynamodb = boto3.client('dynamodb')
dynamodb.put_item(TableName='temporal', Item=item2)
this is the error
Parameter validation failed: Invalid type for parameter Item.ruc, value: 789456123, type: <class 'str'>, valid types: <class 'dict'> Invalid type for parameter Item.dni, value: , type: <class 'str'>, valid types: <class 'dict'> Invalid type for parameter Item.number_operation, value: XXXXXXXXXX, type: <class 'str'>, valid types: <class 'dict'> Invalid type for parameter Item.name, value: THIS IS A STRING, type: <class 'str'>, valid types: <class 'dict'>
Solution 1:[1]
As the error specified, the input data type has to be a dictionary instead of a string.
Do this instead:
dictItems = json.load(object_summary.get()['Body'])
item2 = {
"ruc" : {'N': dictItems['ruc']},
...
}
dynamodb = boto3.client('dynamodb')
dynamodb.put_item(TableName='temporal', Item=item2)
where "ruc" : dictItems['ruc']
is change to "ruc" : {'N': dictItems['ruc']}
.
Solution 2:[2]
As explained in detail here in DynamoDB's documentation, DynamoDB's low-level API is JSON based and because JSON data types do not exactly correspond with DynamoDB's types, there is a more complicated representation of the different types. For example, to send the number 789456123
you wanted to send as part of the request, you can't simply send this number - instead you need to send the following object: { "N": "789456123"}
. This is a map, the key is the type ("N" means a number) and the value is the content of this number - a JSON string, not a JSON number, so as not to loose precision when the JSON library handles it).
The boto3's "client" library, which you are using, uses this low-level API, so you must pass { "N": "789456123"}
instead of 789456123
.
But there's a better and easier approach: boto3 also has a "resource" library, which gives you more or less the same functions - but their parameters are normal Python types instead of low-level API objects. So you can pass a Python integer normally, and it will be passed to the API as a "number" object without you needing to do this conversion explicitly. You also get to enjoy the opposite conversion when you read from the table.
You should switch your code to use a "resource" instead of a "client".
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Nadav Har'El |