DynamoDB JsonMarshaller 无法反序列化对象列表

2022-09-03 09:56:45

我有一个 Java 类,它是 DynamoDB 中表的数据模型。我想使用 Dynamo 中的 to 和 items。类的一个成员是 .因此,我使用 来序列化和反序列化此字段。DynamoDBMappersaveloadList<MyObject>JsonMarshaller<List<MyObject>>

该列表可由 成功序列化。但是,当我尝试检索条目并读取列表时,它会引发异常:.看起来将数据反序列化为 而不是 。我怎样才能摆脱这个问题?JsonMarshallerjava.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to MyObjectJsonMarshallerLinkedHashMapMyObject

The MCVE:

// 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; }

  @DynamoDBMarshalling(marshallerClass = ObjectListMarshaller.class)
  public List<MyObject> getObjects() { return this.objects; }
  public void setObjects(List<MyObject> objects) { this.objects = objects; }
}

// MyObject.java
public class MyObject {
  private String name;
  private String property;

  public MyObject() { }
  public MyObject(String name, String property) {
    this.name = name;
    this.property = property;
  }

  public String getName() { return this.name; }
  public void setName(String name) { this.name = name; }

  public String getProperty() { return this.property; }
  public void setProperty(String property) { this.property = property; }
}

// ObjectListMarshaller.java
public class ObjectListMarshaller extends JsonMarshaller<List<MyObject>> {}

// Test.java
public class Test {
  private static DynamoDBMapper mapper;

  static {
    AmazonDynamoDBClient client = new AmazonDynamoDBClient(new ProfileCredentialsProvider()
    mapper = new DynamoDBMapper(client);
  }

  public static void main(String[] args) {
    MyObject obj1 = new MyObject("name1", "property1");
    MyObject obj2 = new MyObject("name2", "property2");
    List<MyObject> objs = Arrays.asList(obj1, obj2);

    Model model = new Model("id1", objs);
    mapper.save(model); // success

    Model retrieved = mapper.load(Model.class, "id1");
    for (MyObject obj : retrieved.getObjects()) { // exception
    }
  }
}

答案 1

在较新版本中,仅与以下各项配合使用:

@DynamoDBAttribute(attributeName = "things")
public List<Thing> getThings() {
    return things;
}

public void setThings(final List<Thing> things) {
    this.things = things;
}

鉴于该事物标注如下:

@DynamoDBDocument
public class Thing {
}

答案 2

此处的部分问题在于整个 DynamoDB Mapper SDK 如何处理泛型。有一个方法,其中要反序列化的类作为参数传递。问题是存在类型擦除,并且SDK没有提供易于处理的操作。Jackson在某些情况下更聪明(使用Jackson),这解释了为什么该方法可以正常工作。interface DynamoDBMarshaller<T extends Object>T unmarshall(Class<T> clazz, String obj)JsonMarshallerserialize

您需要为反序列化提供更好的实现。一种方法是实现接口而不是扩展另一个接口(我的观点),这样你就可以更好地控制类型的序列化方式。DynamoDBMarshaller

下面是一个示例,它本质上是 复制/粘贴 ,并在反序列化中稍作调整,以便为您提供一个想法:JsonMarshallerList

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMarshaller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.type.CollectionType;

import java.util.List;

import static com.amazonaws.util.Throwables.failure;

public class MyCustomMarshaller implements DynamoDBMarshaller<List<MyObject>> {

    private static final ObjectMapper mapper = new ObjectMapper();
    private static final ObjectWriter writer = mapper.writer();

    @Override
    public String marshall(List<MyObject> obj) {

        try {
            return writer.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw failure(e,
                          "Unable to marshall the instance of " + obj.getClass()
                          + "into a string");
        }
    }

    @Override
    public List<MyObject> unmarshall(Class<List<MyObject>> clazz, String json) {
        final CollectionType
            type =
            mapper.getTypeFactory().constructCollectionType(List.class, MyObject.class);
        try {
            return mapper.readValue(json, type);
        } catch (Exception e) {
            throw failure(e, "Unable to unmarshall the string " + json
                             + "into " + clazz);
        }
    }
}

推荐