Pallavi Kaushik
Pallavi Kaushik

Reputation: 159

DynamoDbMapper ScanExpression not able to Map into Java Object

I am using DynamoDb ScanExpression to scan a table. However, when I try to map List returned from scan into Java Class it throws error "could not unconvert attribute". Following is the code with which I am scanning the table:

    DynamoDBUtil dynamoDBUtil = new DynamoDBUtil();
    AmazonDynamoDB dynamoDBClient = dynamoDBUtil.getDynamoDBClient();
    DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
    DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
    scanExpression.addFilterCondition(NAME, new 
    Condition().withComparisonOperator(ComparisonOperator.EQ)
            .withAttributeValueList(new AttributeValue().withS(name)));
    List<StudentDomain> scanResult = mapper.scan(StudentDomain.class, 
     scanExpression);

It shows me error in the last line while processing mapper.scan(StudentDomain.class, scanExpression). Following is my StudentDomain class:

@DynamoDBTable(tableName = "studentTable")
 public class StudentDomain {

@DynamoDBHashKey(attributeName = "studentId")
private String studentId;

@DynamoDBAttribute(attributeName = "details")
@DynamoDBTyped(DynamoDBAttributeType.M)
private Map<String, Object> details;

}

Earlier It was working fine when I was taking Map(String, String) but now when I have changed it into Map(String, Object) , it is throwing unconvert error. However, when instead of scanning I am querying anything with primary key it works fine with Map(String, Object). For querying with primary key I am using getItem() method. Any kind of help will be highly appreciated.

Upvotes: 1

Views: 1165

Answers (1)

F_SO_K
F_SO_K

Reputation: 14829

DynamoDBMapper can handle arbitrary data types. You just need to use the DynamoDBTypeConverted annotation and write a converter class.

Here is an example.

Model class

// Model.java
@DynamoDBTable(tableName = "...")
public class Model {
  private String id;
  private List<MyObject> objects;

  public Model(String id, List<MyObject> objects) {
    this.id = id;
    this.objects = objects;
  }

  @DynamoDBHashKey(attributeName = "id")
  public String getId() { return this.id; }
  public void setId(String id) { this.id = id; }

  @DynamoDBTypeConverted(converter = MyObjectConverter.class)
  public List<MyObject> getObjects() { return this.objects; }
  public void setObjects(List<MyObject> objects) { this.objects = objects; }
}

Converter Class

public class MyObjectConverter implements DynamoDBTypeConverter<String, List<MyObject>> {

    @Override
    public String convert(List<Object> objects) {
        //Jackson object mapper
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String objectsString = objectMapper.writeValueAsString(objects);
            return objectsString;
        } catch (JsonProcessingException e) {
            //do something
        }
        return null;
    }

    @Override
    public List<Object> unconvert(String objectssString) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            List<Object> objects = objectMapper.readValue(objectsString, new TypeReference<List<Object>>(){});
            return objects;
        } catch (JsonParseException e) {
            //do something
        } catch (JsonMappingException e) {
            //do something
        } catch (IOException e) {
            //do something
        }
        return null;
    }
}

Note that in the case above you would need a to use a List implementation type (e.g. ArrayList), rather than List.

Upvotes: 1

Related Questions