如何使用Java DynamoDBMapper类

时间:2015-07-17 16:11:37

标签: java json amazon-dynamodb

我使用亚马逊的DynamoDBMapper Java类将数据保存到DynamoDB表。此代码需要适用于以多种不同方式构建的数据,因此我希望远离编写特定于结构的代码。出于这个原因,我将代码存储为Java中的JSON对象 - 这些对象基本上是美化的HashMaps。

我想将这些JSON对象存储为DynamoDB Dynamo's relatively new JSON Document type

DynamoDBMapper API的工作方式实际上是您编写Java类(通常是POJO),然后添加一些注释,然后将该类的对象传递给DynamoDBMapper,以便它可以将项目放入具有该结构的数据库中Java类的。这适用于我正在做的事情的许多方面,但不是因为我希望这些类包含任意结构的JSON文档。 This is the way you're meant to store JSON documents using DynamoDBMapper,正如您所看到的,它不允许文档的结构是任意的。

我意识到我可以使用Dynamo的putItem()将jsons作为Strings传递给Item对象 - 我只是想在移动方法之前看看我想用DynamoDBMapper做什么。

3 个答案:

答案 0 :(得分:4)

您可以尝试使用DynamoDB Java文档SDK而不是对象映射器。这允许您使用Item类中的fromJSON和toJSON方法序列化和反序列化JSON字符串。查看http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/JavaDocumentAPIItemCRUD.html

答案 1 :(得分:1)

以下是我如何提出如何在DynamoDB中存储任意Map对象的答案。这对于归档已解组为外部对象的REST API响应非常有用。我个人使用它来存档来自PayPal Payment API的REST响应。我不关心他们在REST API中使用的变量或者他们的POJO / bean的结构。我只是想确保我保存一切。

@DynamoDBTable(tableName = "PaymentResponse")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
    @JsonSubTypes.Type(value = PayPalPaymentResponse.class, name = "PayPalPaymentResponse"),
    @JsonSubTypes.Type(value = BatchPayPalPaymentResponse.class, name = "BatchPayPalPaymentResponse")}
    )
public abstract class PaymentResponse {

    // store any arbitrary REST resrponse data in map form so we don't have to worry about the 
    // structure or the actual response itself
    protected Map<String, String> paymentResponseData = Maps.newHashMap();

    public PaymentResponse(PaymentResponseType paymentResponseType) {
        this.paymentResponseType = paymentResponseType;
    }

    public Map<String, String> getPaymentResponseData() { return paymentResponseData; }

    public void setPaymentResponseData(Map<String, String> paymentResponseData) { this.paymentResponseData = paymentResponseData; }

    @Override
    public String toString() {
        return Arrays.toString(paymentResponseData.entrySet().toArray());
    }
}

public class ConverterUtils {

      public static BatchPayPalPaymentResponse getBatchPayPalPaymentResponse(PayoutBatch payoutBatch) throws IOException {
        //read in the PayoutBatch response data and convert it first to a JSON string and then convert the
        //JSON string into a Map<String, String>
        Map<String, String> responseData = objectMapper.readValue(objectMapper.writeValueAsString(payoutBatch), new TypeReference<Map<String, String>>() {});
        BatchPayPalPaymentResponse batchPayPalPaymentResponse = new BatchPayPalPaymentResponse(responseData);
        return batchPayPalPaymentResponse;
    }

    public static PayPalPaymentResponse getSinglePayPalPaymentResponse(PayoutItemDetails payoutItemDetails) throws IOException {
        //read in the paypal PayoutItemDetails response data and convert it first to a JSON string and then convert the
        //JSON string into a Map<String, String>
        Map<String, String> responseData = objectMapper.readValue(objectMapper.writeValueAsString(payoutItemDetails), new TypeReference<Map<String, String>>() {});
        PayPalPaymentResponse payPalPaymentResponse = new PayPalPaymentResponse(responseData);
        return payPalPaymentResponse;

    }
}

public class BatchPayPalPaymentResponse extends PaymentResponse {
    public BatchPayPalPaymentResponse(Map<String, String> responseData) {
        super(responseData);
    }
    ....
    ....
    ....
}

public class PayPalPaymentResponse extends PaymentResponse {
    public PayPalPaymentResponse(Map<String, String> responseData) {
        super(responseData);
    }
    ....
    ....
    ....
}

现在您可以致电mapper.save(instanceOfPaymentResponse)。请注意,我的代码还包括如何使用Jackson解析器来挑选和选择要解组的PaymentResponse子类。那是因为在将我的类放入数据库之前,我使用DynamoDBTypeConverter将我的类编组为一个字符串。

最后,为了完整性,我会投入我的转换器,所以这一切都很有意义。

public class PaymentResponseConverter implements DynamoDBTypeConverter<String, PaymentResponse> {

    private static final ObjectMapper objectMapper = new ObjectMapper();
    static {
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    @Override
    public String convert(PaymentResponse object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException(String.format("Received invalid instance of PaymentResponse and cannot marshal it to a string (%s)", e.getMessage()));
        }
    }

    @Override
    public PaymentResponse unconvert(String object) {
        try {
            return objectMapper.readValue(object, PaymentResponse.class);
        } catch (IOException e) {
            throw new IllegalArgumentException(String.format("Unable to convert JSON to instance of PaymentResponse. This is a fatal error. (%s)", e.getMessage()));
        }
    }
}

答案 2 :(得分:0)

我遇到了同样的问题,我自己将对象序列化和反序列化为json字符串,然后将它们存储为字符串。 DynamoDB的整个Document概念是IMHO只是一个美化的对象序列化器。只有当您需要在dynamodb操作(例如扫描,投影)中访问对象内的属性时,才有必要使用json文档类型。如果我们的数据对dynamodb不透明,那么你最好使用字符串。