简体   繁体   中英

DynamoDB nested map to Java Object

I am using a DynamoDB-table with DynamoDBAttributeType.M maps nested in one another. The field of my table I'm having problems with looks like this:

"Data": {

"EnglishName": "Balcony",
"High": {
  "Status": true,
  "Triggered": true,
  "Value": 5
},
"Low": {
  "Status": true,
  "Triggered": false,
  "Value": 1
},
"TagName": "tag1"
}

all the keys of the map are Strings and some of the values are Strings and some are maps. In my Java code that data is represented by a class, which is an attribute of another class, which represents whole table. Attributes 'Low' and 'High' are also represented by Java class and attributes of data class.

I have tried to map it to Java object using many ways, mostly by DynamoDBTypeConverter. Hardest part is that I can't find any information about this with Google. I only found one example of converter class where attribute type is S not M.

I keep on getting error:

could not unconvert attribute

How this can be done?

Have you tried using a tool like Gson? If you're getting back the DynamoDB response as a JSON string, try this:

Gson gson = new Gson();
Data data = gson.fromJson(jsonString, Data.class);

Finally I have a functioning solution. Basically the answer is to use Map<String, Attributevalue> and desired object type in DynamoDBTypeConverter like this:

public class DataConverter implements DynamoDBTypeConverter<Map<String, AttributeValue>, Data> {

@Override
public Map<String, AttributeValue> convert(Data data) {
    
    ObjectMapper mapper = new ObjectMapper();
    
    Item item = new Item()
           .withString("englishName", data.getEnglishName())
           .withMap("high", mapper.convertValue(data.getHigh(), Map.class))
           .withMap("low", mapper.convertValue(data.getLow(), Map.class))
           .withString("tagName", data.getTagName());

    return ItemUtils.toAttributeValues(item);
}

@Override
public Data unconvert(Map<String, AttributeValue> data) {
    Data tagData = new Data();
    try {
        ObjectMapper mapper = new ObjectMapper();
        String item = ItemUtils.toItem(data).toJSON();
        JsonNode json = mapper.readTree(item);
        tagData = mapper.convertValue(json, Data.class);
        
    } catch (JsonProcessingException ex) {
        Logger.getLogger(TagDataConverter.class.getName()).log(Level.SEVERE, null, ex);
    }       
    return tagData;
}    

I also needed to write type converters to attributes that are objects and annotate them in class:

public class Data {

    private String tagName;

    private String englishName;

    @DynamoDBTypeConverted(converter = AlertConverter.class)
    private Alert low;

    @DynamoDBTypeConverted(converter = AlertConverter.class)
    private Alert high;

The AlertConverter.class is an ordinary DynamoDBTypeConverter that takes in <String, Alert>.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM