Разобрать вложенный json как необработанную строку

Я пишу функцию Lambda, которая получает объект очереди SQS. SQS отправляет объект json в виде строкового значения в SQS.

Когда я получаю запрос в Lambda, AWS заворачивает его в новый JSON, и, поскольку json является строковым значением, он становится недействительным json.

(Пример) JSON выглядит так:

{"uuid ":"someuuid"} 

Мы отправляем это как строку в SQS. Затем AWS оборачивает это во что-то вроде:

{
  "Records": [
    {
      "messageId": "somemesasgeid",
      "receiptHandle": "MessageReceiptHandle",
      "body": {
          "Message":"{"uuid":"someUuid"}"
      },
      "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "sometimestamp",
        "SenderId": "someid",
        "ApproximateFirstReceiveTimestamp": "sometimestamp"
      },
      "messageAttributes": {},
      "md5OfBody": "somebody",
      "eventSource": "aws:sqs",
      "eventSourceARN": "someARN",
      "awsRegion": "eu-west-1"
    }
  ]
}

Теперь body.Message недействителен Json. Я попытался разобрать его как необработанное значение, такое как Как я могу включить необработанный JSON в объект с помощью Джексона?, но он продолжает жаловаться, что нашел u там, где ожидал объект, разделенный запятыми.

Поскольку я не могу отправить необработанный json в SQS и должен его преобразовать в строку, как мне проанализировать это в объект, где я могу получить сообщение json?

Я попытался создать pojo и попробовать указанную выше ссылку, но Джексон продолжает жаловаться на переменную сообщения.

--- обновить код ---

private Response HandleServiceRequest(Map<String, Object> input) {

List<String> records = (List<String>) input.get("Records");
    for(String r : records) {
        SqsMessage m = objectMapper.readValue(r, SqsMessage.class);
    }
}
public class SqsMessage {
    // all other values
    SqsBody body;

// getters/setters
}
public class SqsBody {
// all other values
@JsonProperty("Message")
private Object message;
// getters/setters
@JsonRawValue
public String getMessage() {
   message == null ? null : message.toString();
}

public void setMessage(Object message){
this.message = message;
}
}

Это то, что у меня есть сейчас. Я попытался изменить сообщение на String, но это ничего не изменило.

Не могли бы вы попытаться обработать этот вложенный json как строку вместо json или pojo? Таким образом, он должен быть экранирован и привести к чему-то вроде "Message":"{\"uuid\":\"someUuid\"}"

Thomas 21.06.2019 11:50

Я пробовал это. String и даже Object. Джексон все равно попытается разобрать его. Я мог бы попытаться избежать json, прежде чем отправлять его в SQS. Попробую это

MrM 21.06.2019 11:53

Джексон не должен пытаться анализировать строковое значение, пока вы не скажете ему, что "Message" — это что-то другое. Можете ли вы предоставить дополнительную информацию, например. минимальный воспроизводимый пример?

Thomas 21.06.2019 11:55

@ Томас Это то, что у меня есть сейчас. Я попытался изменить сообщение на String, но для меня это не имело значения.

MrM 21.06.2019 12:03

Ну, вы опубликовали, как вы пытаетесь разобрать json, но я понял, как вы это делаете генерировать? "Message":"{"uuid":"someUuid"}" не является допустимым json, поэтому у Джексона в любом случае возникнут проблемы с его синтаксическим анализом. Вам нужно, чтобы вложенный json был экранирован при генерации, т. Е. Привести его к форме, как я предложил в своем первом комментарии, - только если содержимое строки правильно экранировано, Джексон сможет прочитать строку целиком.

Thomas 21.06.2019 12:10

Человек, написавший на другом конце, говорит, что убегает, он еще раз проверит. вернется к вам

MrM 21.06.2019 12:18

Аналогично в Python, но, возможно, здесь работает то же самое: Как автоматически исправить недопустимую строку JSON?. (Я только что попробовал, это работает в Python для этого примера и должно работать и в Java, если сообщения об ошибках похожи.) Конечно, предпочтительным решением было бы не создавать этот недопустимый JSON в первую очередь.

tobias_k 21.06.2019 12:19

@Thomas Итак, мы перепроверили и избежали их, и это действительно решило проблему. Однако я не могу принять ваш комментарий в качестве ответа.

MrM 21.06.2019 12:36

@tobias_k Спасибо за ссылку, это было бы хорошим последним средством, но выяснение того, где синтаксический анализ идет не так, было действительно предпочтительным.

MrM 21.06.2019 12:39

Добавлю ответ ;)

Thomas 21.06.2019 14:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
10
1 333
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основная проблема заключается в том, что "Message":"{"uuid":"someUuid"}" не является допустимым json, и поэтому Джексон не может разобрать эту часть. С точки зрения json значение "Message" равно "{", поэтому следующее uuid вызывает ошибку.

Чтобы справиться с этим, вам нужно правильно экранировать вложенный json, чтобы он выглядел как любая другая строка для Джексона, то есть вы хотели бы получить что-то вроде этого:

"Message":"{\"uuid\":\"someUuid\"}"

Здесь значение "Message" равно "{\"uuid\":\"someUuid\"}", и, таким образом, Джексон может взять эту строку и обработать ее дальше (поместить ее в строку или распаковать и проанализировать).

Это означает, что вы не должны пытаться решать проблему на стороне синтаксического анализа, а на стороне генерации, то есть там, где создается тело запроса для HandleServiceRequest(...).

Другие вопросы по теме