Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ParameterVailidation Failed When Sending List to DynamoDB

I have a simple Python function on AWS Lambda that just puts some data into a DynamoDB table and as far as I can tell, I'm following the correct format as per the Boto3 documentation for the put_item() function. I'm getting the following error that I can't seem to debug:

"errorMessage": 
"Parameter validation failed:\nInvalid type for parameter 
Item.GSRResults.L[0], value: 3.8, type: <class 'float'>, valid types: <class 'dict'>
\nInvalid type for parameter Item.GSRResults.L[1], value: 3.4, type: <class 'float'>, valid types: <class 'dict'>\... snip...
\nInvalid type for parameter Item.GSRResults.L[9], value: 3.3, type: <class 'float'>, valid types: <class 'dict'>",
  "errorType": "ParamValidationError",
  "stackTrace": [
    [
      "/var/task/index.py",
      39,
      "upload_test",
      "Item=item"
    ], 

Here is the Python function:

def upload_test(event, context):
    if event['httpMethod'] == 'POST':
        info = event['body']
        item = info['Item']
        return respond(None, dynamo.put_item(
            TableName="TestResults",
            Item=item))

This is the JSON I am sending:

{
  "body": {
    "Item": {
      "UID": {
        "S": "U999999"
      },
      "PID": {
        "S": "P444444"
      },
      "GSRResults": { "L": [3.8,3.4,3.3,2.8,1.3,3.2,4.3,2.1,3.2,3.3] }
    }
  },
  "httpMethod": "POST"
}
like image 328
empty_space Avatar asked Nov 01 '17 17:11

empty_space


2 Answers

Use the following Client.put_item example for the Client API:

import boto3
client = boto3.client('dynamodb')

item1 = {
  "id": {
    "S": "1",
  },
  "name": {
    "S": "Testing"
  },
  "age": {
    "N": "22"
  },
  "grades": {
    "L": [ {"N": "3.50"}, {"N": "3.1415926"} ]
  }
}

client.put_item(TableName='test', Item=item1);

Or use the following Table.put_item example for the Resource API:

import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('test')

item2 = {
  "id": "2",
  "name": "Testing2",
  "age": 22,
  "grades": [ decimal.Decimal('3.50'), decimal.Decimal('3.1415926') ]
}

table.put_item(Item=item2)

It's very easy to find that you are using a Resource-level object (such as Table) but accidentally looking at the Client-level API documentation because the methods unfortunately have the same names (e.g. put_item).

See a related post on when to use a boto3 Client vs a Resource. The key difference here is that the Resource API marshals/unmarshals data to/from native Python data types automatically, while the Client API does not.

like image 119
jarmod Avatar answered Oct 05 '22 08:10

jarmod


The float values should be set as demical in Python.

Import:-

import decimal

Set the value as decimal:-

"GSRResults": [decimal.Decimal('3.8'),decimal.Decimal('3.4')]

Dynamodb Type for Python

For types that involve numbers, it is recommended that Decimal objects are used to be able to round-trip the Python type.

like image 36
notionquest Avatar answered Oct 05 '22 07:10

notionquest