Я пишу функцию 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, но это ничего не изменило.
Я пробовал это. String и даже Object. Джексон все равно попытается разобрать его. Я мог бы попытаться избежать json, прежде чем отправлять его в SQS. Попробую это
Джексон не должен пытаться анализировать строковое значение, пока вы не скажете ему, что "Message" — это что-то другое. Можете ли вы предоставить дополнительную информацию, например. минимальный воспроизводимый пример?
@ Томас Это то, что у меня есть сейчас. Я попытался изменить сообщение на String, но для меня это не имело значения.
Ну, вы опубликовали, как вы пытаетесь разобрать json, но я понял, как вы это делаете генерировать? "Message":"{"uuid":"someUuid"}" не является допустимым json, поэтому у Джексона в любом случае возникнут проблемы с его синтаксическим анализом. Вам нужно, чтобы вложенный json был экранирован при генерации, т. Е. Привести его к форме, как я предложил в своем первом комментарии, - только если содержимое строки правильно экранировано, Джексон сможет прочитать строку целиком.
Человек, написавший на другом конце, говорит, что убегает, он еще раз проверит. вернется к вам
Аналогично в Python, но, возможно, здесь работает то же самое: Как автоматически исправить недопустимую строку JSON?. (Я только что попробовал, это работает в Python для этого примера и должно работать и в Java, если сообщения об ошибках похожи.) Конечно, предпочтительным решением было бы не создавать этот недопустимый JSON в первую очередь.
@Thomas Итак, мы перепроверили и избежали их, и это действительно решило проблему. Однако я не могу принять ваш комментарий в качестве ответа.
@tobias_k Спасибо за ссылку, это было бы хорошим последним средством, но выяснение того, где синтаксический анализ идет не так, было действительно предпочтительным.
Добавлю ответ ;)




Основная проблема заключается в том, что "Message":"{"uuid":"someUuid"}" не является допустимым json, и поэтому Джексон не может разобрать эту часть. С точки зрения json значение "Message" равно "{", поэтому следующее uuid вызывает ошибку.
Чтобы справиться с этим, вам нужно правильно экранировать вложенный json, чтобы он выглядел как любая другая строка для Джексона, то есть вы хотели бы получить что-то вроде этого:
"Message":"{\"uuid\":\"someUuid\"}"
Здесь значение "Message" равно "{\"uuid\":\"someUuid\"}", и, таким образом, Джексон может взять эту строку и обработать ее дальше (поместить ее в строку или распаковать и проанализировать).
Это означает, что вы не должны пытаться решать проблему на стороне синтаксического анализа, а на стороне генерации, то есть там, где создается тело запроса для HandleServiceRequest(...).
Не могли бы вы попытаться обработать этот вложенный json как строку вместо json или pojo? Таким образом, он должен быть экранирован и привести к чему-то вроде
"Message":"{\"uuid\":\"someUuid\"}"