DynamoDB: как прочитать фактическое значение поля из AttributeValue?

Я использую AWS Lambda, написанный на java, для обработки потоков DynamoDB. Вот код:

public class DDBEventProcessor implements
        RequestHandler<DynamodbEvent, String> {

    public String handleRequest(DynamodbEvent ddbEvent, Context context) {
        for (DynamodbStreamRecord record : ddbEvent.getRecords()){
            Map<String, AttributeValue> tmp = record.getDynamodb.getNewImage();   
            
            //convert tmp to Map<String, Object> here
        }
    }
}

Мне нужно обработать запись дальше.

Для этого его нужно преобразовать в Map<String, Object>.
Полученные данные будут иметь формат: { "id":{"s":"777"}}.
Но я хочу преобразовать их в {"id":"777"}, чтобы я мог легко анализировать объект карты . Но есть и вложенные массивы и карты. Также запись очень сложная, состоящая из вложенных массивов и карт. Как этого добиться?


person mightyMouse    schedule 16.03.2021    source источник
comment
Как его нужно преобразовать? AttributeValue уже является Object (AttributeValue extends Object). Вам нужен актерский состав или фактическое преобразование?   -  person knittl    schedule 16.03.2021
comment
Мне нужно применить его к объектам карты. в основном преобразуется в карту пар ключ-значение, где значение может быть списком, картой, строкой или int и т. д.   -  person mightyMouse    schedule 16.03.2021
comment
Зачем именно нужна карта типа Map<String, Object>?   -  person knittl    schedule 16.03.2021


Ответы (3)


Я понимаю, что вы хотите преобразовать Map<String, AttributeValue> в Map<String, Object>, поэтому то, что ответил @knittl, является правильным, если вам нужен Object, но вы хотели получить буквальное значение каждого поля вместо простого преобразования AttributeValue в Object, если я правильно вас понял.

Итак, если вы проверяете код для AttributeValue:

public class AttributeValue implements Serializable, Cloneable {
  private String s;
  private String n;
  private ByteBuffer b;
  private List<String> sS;
  private List<String> nS;
  private List<ByteBuffer> bS;
  private Map<String, AttributeValue> m;
  private List<AttributeValue> l;
  private Boolean nULLValue;
  private Boolean bOOL;
  ...

Вы можете видеть, что перечислено много полей типа, и они используются для принудительного ввода. Мы еще вернемся к этому.
Поскольку вы получаете это как событие DynamoDB Stream, нам нужен класс модели, о котором мы можем поговорить :)

Допустим, у нас есть этот простой класс модели:

public class Employee {
     String name = "John";
     int age = 25;
     boolean isPermanent = true;
}

Когда вы создаете / обновляете запись указанной выше модели, DynamoDB генерирует событие, которое содержит старую запись (изображение) и новую (это, конечно, зависит от вашей конфигурации).

Теперь вернемся к проверке типа:
name поле равно String, это приведет к вводу ключа name и значению atrbValue.s = "John"
age в поле int, это приведет к вводу ключа age и значения atrbValue.n = "25"
Поле isPermanent равно boolean, в результате вводится ключ isPermanent и значение atrbValue.bOOL = true

Итак, вы можете видеть, что нет ярлыка для преобразования Map<String, AttributeValue> в Map<String, Object>.


Но вы можете это сделать:

Map<String, Object> result = new HashMap<String, Object>(); 
AttributeValue defaultValue = new AttributeValue();

result.put("name", image.getOrDefault("name", defaultValue).getS());
result.put("age", Integer.valueOf(image.getOrDefault("age", defaultValue).getN()));
result.put("isPermanent", image.getOrDefault("isPermanent", defaultValue).getBOOL());

Подробнее о AttributeValue см. в документации AWS.

person dsharew    schedule 24.03.2021
comment
Оказалось, что класс com.amazonaws.services.dynamodbv2.document.ItemUtils - это именно то, что мне нужно. - person mightyMouse; 25.03.2021

Если типы совместимы, вы можете создать копию карты с правильными универсальными типами:

final Map<String, AttributeValue> tmp = record.getDynamodb.getNewImage();   
final Map<String, Object> map = new HashMap<>(tmp)
person knittl    schedule 16.03.2021
comment
Полученные данные будут иметь формат: {id: {s: 777}}. я хочу преобразовать его в {id: 777}, чтобы я мог легко анализировать объект карты. Но есть и вложенные массивы и карты. - person mightyMouse; 16.03.2021
comment
@mightyMouse ооочень ... какой у тебя настоящий вопрос? :) - person knittl; 16.03.2021

Этого легко добиться с помощью встроенного класса ItemUtils. Проверьте реализацию toSimpleMapValue. Реализация является рекурсивной по своей природе и проходит по схеме Map ‹String, AttributeValue› и преобразует ее в простой объект карты. Я просто скопировал необходимые для преобразования методы.

person mightyMouse    schedule 24.03.2021