Reputation: 159
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
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