Skip to content

aws-dynamodb-local:3.1.0 responds differently than 2.6.1 when DynamoDB contains empty M value

0

For data "settings": { "M": {}}, the client side handling is the same

private final DynamoDbStreamsClient client;
GetRecordsResponse result = client.getRecords(GetRecordsRequest.builder().shardIterator(currentShardIter).build());
                        currentShardIter = result.nextShardIterator();
                        shardPositions.put(shardId, result.nextShardIterator());
                        result.records().stream().map(sr -> {

aws-dynamodb-local:2.6.1 responds sr with settings=AttributeValue(M={}) aws-dynamodb-local:3.1.0 responds sr with settings=AttributeValue()

I think 2.6.1 behavior more aligns with the actual value since AttributeValue() is for null and AttributeValue(M={}) is for empty map.

asked a year ago225 views

1 Answer
-1

There appears to be a behavior change between DynamoDB Local versions 2.6.1 and 3.1.0 in how empty map values are represented in responses.

In version 2.6.1, an empty map value is returned as AttributeValue(M={}), which correctly represents an empty map structure.

In version 3.1.0, the same empty map is returned as just AttributeValue(), which typically represents a null value rather than an empty map.

You're correct in your assessment that the 2.6.1 behavior more accurately represents the actual data structure. An empty map ("settings": { "M": {}}) should be represented as AttributeValue(M={}) rather than as a null value (AttributeValue()).

This discrepancy could cause issues in applications that rely on distinguishing between null values and empty maps. When working with empty collections in DynamoDB, it's important to note that while empty binary values are supported, and reading empty string values is supported, there are specific behaviors around empty values that may differ between local development environments and the live service.

If this inconsistency is causing problems in your application, you might need to add additional null checking or type verification in your code when working with potentially empty map values, especially if you plan to deploy to the live DynamoDB service.
Sources
Working with the .NET object persistence model and DynamoDB - Amazon DynamoDB
Working with the .NET document model in DynamoDB - Amazon DynamoDB
ExecuteStatement with Limit on DynamoDB Local returns wrong result set when using descending ordering | AWS re:Post

answered a year ago

  • I don't think that's expected.

    The following test fails in 3.1.0 but succeeds in 2.6.1

    • PutItem to dynamodb
    • DynamoDbClient.getItem() vs DynamoDbStreamClient.getRecords()
    • Also tested against real AWS DynamoDB and the response aligns with 2.6.1
    dynamoDbClient.putItem(r -> r.tableName(tableName)
            .item(Map.of("partitionKey", AttributeValue.fromS("pk"),
                    "sortKey", AttributeValue.fromS("sk"),
                    "data", AttributeValue.fromM(Map.of()))));
    var item = dynamoDbClient.getItem(r -> r.tableName(tableName)
            .key(Map.of("partitionKey", AttributeValue.fromS("pk"),
                    "sortKey", AttributeValue.fromS("sk"))));
    assertEquals(AttributeValue.fromM(Map.of()), item.item().get("data"));
    var shards = dynamoDbStreamsClient.describeStream(r -> r.streamArn(streamArn))
            .streamDescription().shards();
    var it = dynamoDbStreamsClient.getShardIterator(r -> r.streamArn(streamArn)
            .shardId(shards.get(0).shardId()).shardIteratorType(ShardIteratorType.TRIM_HORIZON)).shardIterator();
    var recs = dynamoDbStreamsClient.getRecords(r -> r.shardIterator(it).limit(10)).records();
    assertEquals(AttributeValue.fromM(Map.of()), recs.get(0).dynamodb().newImage().get("data"));
    

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.