当前位置: 首页 > 面试题库 >

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

娄浩荡
2023-03-14
问题内容

我有一个Java类,它是DynamoDB中表的数据模型。我想使用Dynamo 的DynamoDBMapperto
saveloaditem。班上一名成员是一名List<MyObject>。因此,我使用JsonMarshaller<List<MyObject>>来对该字段进行序列化和反序列化。

该列表可以通过成功地序列化JsonMarshaller。但是,当我尝试取回条目并阅读列表时,它会引发异常:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to MyObject。好像JsonMarshaller将数据反序列化为LinkedHashMap而不是MyObject。我如何摆脱这个问题?

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

问题答案:

问题的一部分是整个DynamoDB Mapper SDK如何处理泛型。该interface DynamoDBMarshaller<T extends Object>有一个方法T unmarshall(Class<T> clazz, String obj),其中,所述类反序列化到被作为参数传递。问题在于存在类型擦除,而SDK并不能轻松解决该问题。杰克逊在某些情况下会更聪明(JsonMarshaller使用杰克逊),这说明了该serialize方法正确工作的原因。

您需要为反序列化提供更好的实现。您可以执行此操作的一种方法是实现DynamoDBMarshaller接口,而不是扩展另一个接口(我认为),以便您可以更好地控制类型的序列化方式。

这是一个本质上是复制/粘贴的示例,JsonMarshaller对反序列化进行了细微调整,List以使您有一个想法:

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


 类似资料:
  • (数据类)实体。JAVA (数据类)实体。JAVA 我试着说: 我犯了一个错误: 我已经把和我错过了什么?

  • 问题内容: 使用取消序列化对象时出现以下错误: JSONMappingException无法构造org.springframework.data.Page的实例,问题:抽象类型只能用其他类型信息实例化。 我正在尝试将JSON字符串序列化为表示类型页面的Spring数据对象T。 该User班是一个简单的与和名称。我要反序列化的字符串是: 这将导致异常: 由于是对象,因此无法修改它,我认为这与我在别处

  • 问题内容: 我试图序列化和反序列化内部对象的数组列表: HairList对象也是一个可序列化的对象。 此代码执行返回以下错误: 排队 我不知道我在做什么错。你能给个小费吗? 更新: 解决: 仅使用HairBirt的本机数组而不是ArrayList即可工作: 代替 感谢大家的帮助。 问题答案: 不要使用-而是使用二进制数据并对它进行base64编码,以将其转换为字符串而不会丢失信息。 我强烈怀疑这是

  • 本文向大家介绍java对象的序列化和反序列化,包括了java对象的序列化和反序列化的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了java对象的序列化和反序列化,供大家参考,具体内容如下 1. 什么是序列化        将对象转换为字节流保存起来,比如保存到文件里,并在以后还原这个对象,这种机制叫做对象序列化。(补充一句:把对象保存到永久存储设备上称为持久化) 2. 怎么实现序列化

  • 我已经开始将一个项目从使用Java标准日期迁移到Joda DateTime。 我的项目使用XML序列化将对象保存到XML文件中。在这个特殊的例子中,我有一个Item类,它有一个DateTime属性。 在某个时候,我正在初始化对象,包括像这样的DateTime属性: 我使用XMLEncoder使用辅助类序列化项目: 显然,日期时间被保存在xml中。。。但毫无价值: 显然,它没有保存任何东西,但不,它