2016-11-01 108 views
0

我有一个特定的用例,其中我将来自DynamoDB中的一个表的结果存储为另一个DynamoDB中的序列化方式。 现在,当我使用GSON反序列化所检索的数据, 我得到这个错误:使用gson反序列化DynamoDBResults失败

java.lang.RuntimeException: Unable to invoke no-args constructor for class java.nio.ByteBuffer. Register an InstanceCreator with Gson for this type may fix this problem. 
     at com.google.gson.internal.ConstructorConstructor$12.construct(ConstructorConstructor.java:210) 
     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:186) 
     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:103) 
     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196) 
     at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) 
     at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:187) 
     at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145) 
     at com.google.gson.Gson.fromJson(Gson.java:810) 
     at com.google.gson.Gson.fromJson(Gson.java:775) 

我的方法是这样的:

public void store(MyCustomObject obj) { 
String primaryKey = obj.getKey(); 

List<Map<String, AttributeValue>> results = AmazonDynamoDB.query(...).getItems(); 
Gson gson = new Gson(); 
List<String>records = results .stream() 
      .map(mappedResult-> gson.toJson(mappedResult)) 
      .collect(Collectors.toList()); 

Map<String, AttributeValue> attributeMap = transformToAttributeMap(records); 
PutItemRequest putItemRequest = new PutItemRequest().withItem(attributeMap); 
AmazonDynamoDB.putItem(...); 
} 

检索记录的方法看起来是这样的:

public void retrieve(String id) { 
QueryRequest... 
Map<String, AttributeValue> records = DynamoDB.query(...).getItems(); 

List<String> serializedRecords = new ArrayList<>(); 
List<AttributeValue> values = records.get("key"); 
for(AttributeValue attributeValue: values) { 
    serializedRecords.add(attributeValue.getS()); 
} 

Gson gson = new Gson(); 
Type recordType = new TypeToken<Map<String, AttributeValue>>() { }.getType(); 
List<Map<String, AttributeValue>> actualRecords = serializedRecords.stream() 
       .map(record-> gson.fromJson(record, recordType)) 
       .collect(Collectors.toList()); 
} 

我在做什么错?

+0

你有没有尝试做流调用外部相同的转换? – mtyurt

+0

不,我没有尝试过流调用之外的任何东西 – chrisrhyno2003

+0

请首先尝试,我的猜测是关于这一行中的泛型有一个问题:'.map(record-> gson.fromJson(record,recordType))' – mtyurt

回答

0

问题是AttributeValue类有一个字段java.nio.ByteBuffer名称为b。 Gson试图将数据反序列化到它中,但ByteBuffer类没有默认的构造函数。因此,gson无法反序列化b字段。

另一种解决方案是使用AWS SDK的新DynamoDB。以下示例应该可以工作:

AmazonDynamoDBClient client = new AmazonDynamoDBClient(
     new ProfileCredentialsProvider()); 
Item item = new DynamoDB(client).getTable("user").getItem("Id", "user1"); 
String json = item.toJSON(); 
Item deserialized = Item.fromJSON(json); 

您应该根据您的设置修改凭据提供程序。

0

不完全是最好的解决方法/答案,但我能做到这一点:

Item item = new Item().withJSON("document", jsonStr); 
    Map<String,AttributeValue> attributes = InternalUtils.toAttributeValues(item); 
    return attributes.get("document").getM();