Dyanmodb Enchanced клиентские вложенные объекты в формате json

#java #amazon-web-services #amazon-dynamodb #aws-sdk-java-2.0

#java #amazon-веб-сервисы #amazon-dynamodb #aws-sdk-java-2.0

Вопрос:

Я использую вложенный объект (композицию) для представления данных, которые я хочу сохранить, и использую расширенный клиент Dyanmodb как часть AWS Java версии 2 api. В readme объясняется, как сгладить объекты. В одной из версий API удалось сохранить список объектов в виде документов json в dyanmodb.

 public class Customer{
  private String name;
  private List<GenericRecord> recordMetadata;
  //getters and setters for all attributes
}


public class GenericRecord {
  private String id;
  private String details;
  //getters and setters for all attributes
} 
 

Хотелось бы, чтобы он был сохранен, как показано ниже, а не сплющен для обратной совместимости:

 {
  "name": "ABC",
 "recordMetadata": [
  {
    "id":"123",
    "details":"hello"

   },
  {
    "id":"456",
    "details":"yellow"

   }
 ]

}
 

https://github.com/aws/aws-sdk-java-v2/blob/master/services-custom/dynamodb-enhanced/README.md

Ответ №1:

Если я понял, вы хотите сериализовать вложенный объект в строку, точно так @DynamoDBTypeConvertedJson же, как это было сделано с аннотацией DynamoDBMapper in v1 AWS SDK для Java. В версии 2 AWS SDK для Java нет ничего, что можно было бы сделать из коробки, чтобы сделать это. Вам придется написать свой собственный конвертер вручную, как показано ниже.

Но на самом деле нет никакой пользы от сериализации его в виде строки, поэтому вы можете просто сохранить его как вложенный документ. Это не должно требовать каких-либо изменений в опубликованном вами коде. Сохранение его в виде документа имеет такие преимущества, как возможность обновлять одно вложенное поле. Вы никогда не знаете, когда может возникнуть требование, требующее этого, и опять же, я не знаю о каких-либо недостатках хранения его в виде документа.

Примечание: я не думаю @DynamoDbFlatten , что это сработает в вашем случае, потому что нет смысла сглаживать список.

 class GenericRecordListConverter implements AttributeConverter<List<GenericRecord>> {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static GenericRecordListConverter create() {
        return new GenericRecordListConverter();
    }

    @Override
    public AttributeValue transformFrom(List<GenericRecord> input) {
        try {
            return AttributeValue.builder().s(MAPPER.writeValueAsString(input)).build();
        }
        catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<GenericRecord> transformTo(AttributeValue input) {
        try {
            return MAPPER.readValue(input.s(), new TypeReference<List<GenericRecord>>() {});
        }
        catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public EnhancedType<List<GenericRecord>> type() {
        return EnhancedType.listOf(GenericRecord.class);
    }

    @Override
    public AttributeValueType attributeValueType() {
        return AttributeValueType.S;
    }

}
 

Ответ №2:

Это решено, не нужен конвертер см.:

 .addAttribute(EnhancedType.listOf(EnhancedType.documentOf(GenericRecord.class,TableSchema.fromClass(GenericRecord.class))),
                    a -> a.name("recordMetadata").getter(Customer::getRecordMetadata)
                            .setter(Customer::setRecordMetadata)  )
 

Официальный ответ:

https://github.com/aws/aws-sdk-java-v2/issues/2265