Почему это свойство JSON регистрируется как неопределенное? - PullRequest
0 голосов
/ 06 июля 2019

У меня есть лямбда-нода nodejs, у которой в качестве события есть очередь SQS, подписанная на тему SNS.

Лямбда выглядит так:

'use strict';

import { Handler } from 'aws-lambda';

const myLambda: Handler = async (event: any = {}) => {
  let incomingMessage = JSON.stringify(event.Records[0].body);
  console.log('Received event:', incomingMessage); # log1
  console.log('parsed event',JSON.parse(incomingMessage)); # log2
  var type = JSON.parse(JSON.stringify(incomingMessage)).Type;
  console.log('Message received from SNS:', type); # log3
  return { };
};

export { myLambda }

Я аннотировал три строки журнала, потому что это немного облегчит разговор.

log1: Показывает голый текст события. log2: Это показывает хороший формат JSON (спасибо cloudwatch) сообщения:

{
    "Type": "Notification",
    "MessageId": "9245d801-2fe5-58ed-b667-8d9b73b2ff85",
    "TopicArn": "arn:aws:sns:eu-west-1:0123456:TopicName",
    "Subject": "Amazon SES Email Receipt Notification",
    "Message": "{json goes here}",
    "Timestamp": "2019-07-06T08:21:43.474Z",
    "SignatureVersion": "1",
    "Signature": "Signature goes here",
    "SigningCertURL": "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-1234567.pem",
    "UnsubscribeURL": "https://url.goes.here"
}

log3: Это просто лог undefined

Я не понимаю, почему он отображается как undefined, а не Notification.

Это я изучаю машинописные / нодные лямбды, так что будьте осторожны.

1 Ответ

2 голосов
/ 07 июля 2019

Оставаться правильно концептуально ориентированным относительно инкапсуляции JSON здесь может быть немного сложно, потому что несколько сервисов взаимодействуют в каскаде.

Когда сервисы AWS взаимодействуют с функциями, развернутыми с использованием сред Lambda среды Node.js дляпоставляя события, они фактически предоставляют всю полезную нагрузку вызова в виде объекта JSON на проводе.Этот слой JSON на самом деле вас не интересует, потому что Lambda прозрачно разбирает его на правильный объект JavaScript и передает его вам как event.

Когда интеграция SQS / Lambda агрегирует события, существуетявляется структурой события с внешним массивом Records в объекте event, и каждый член массива содержит свойства одного сообщения SQS, полученного из действия API SQS ReceiveMessages.На этом уровне также есть сериализация JSON, но, опять же, она прозрачно обрабатывается, и то, что сделано, отменяется, поэтому это не представляет интереса.

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

Среди свойств каждого объекта в массиве Records есть body, который содержит строку сполезная нагрузка из сообщения SQS.

Если вы сами захватываете опубликованное вами сообщение SQS, это body будет содержать в точности те байты тела сообщения, которые отправлены в SQS с SendMessageвызов.Это было бы прозрачно.Что бы вы ни указали, это то, что вы получите, будь то обычный текст, Base-64, JSON, XML и т. Д.

Однако ... у вас есть очередь SQS, которая подписана на тему SNS,

При подключении SNS к SQS:

Сообщение Amazon SQS содержит тему и сообщение, которые были опубликованы в теме вместе с метаданными о сообщении в документе JSON.

https://docs.aws.amazon.com/sns/latest/dg/sns-sqs-as-subscriber.html

«Сообщение Amazon SQS», упомянутое выше, означает тело сообщения - и это то, что вы найдете в свойстве body, например, event.Records[0].body.

"Документ JSON" в body фактически создается SNS.

Когда SNS доставляет сообщение в SQS, он добавляет слой инкапсуляции JSON в свой собственный вывод, поэтомучто другие свойства сообщения сохраняются, а не только полезная нагрузка тела (которую SNS вызывает Message).

Таким образом, вы получаете здесь body, предоставленный в SQS SNS, который SNS имеетзакодировано в JSON.Все, что вам нужно сделать, это проанализировать это в объект JavaScript, используя JSON.parse().

let incomingMessage = JSON.parse(event.Records[0].body); 
let type = incomingMessage.Type;
console.log(type); // 'Notification'

Вы также можете обнаружить, что полезная нагрузка фактического сообщения SNS (сообщения SNS, полученного от SES) являетсяОбъект JSON также.В таком случае:

let message = JSON.parse(incomingMessage.Message);

Обратите внимание, что мы анализируем body в объект, беря атрибут Message из результирующего объекта - который является строкой, содержащей объект JSON -и разбор этого в другой объект.Сверху, то, что мы делаем, в строке выше, чтобы декодировать это самое внутреннее сообщение, эквивалентно этому - показано здесь для иллюстрации принципа:

let message = JSON.parse(JSON.parse(event.Records[0].body).Message);

Это может первоначально показаться вам довольносложный и запутанный, но есть веские причины, почему это необходимо.JSON поддерживает идеальное вложение других JSON и чистых циклов, не путая границы объектов.Оба SNS и SQS поддерживают доставку только текстовых символьных данных - в качестве полезной нагрузки ... поэтому SES создает JSON-представление того, что он хочет вам сообщить , и отправляет его в SNS ... затем SNS создаетJSON-представление того, что он должен вам сказать, и отправляет его в SQS ... так что есть два уровня сериализации JSON, которые вам, в конечном счете, нужно будет отменить для обработки уведомлений о событиях SES> SNS> SQS> Lambda.


В качестве напоминания:

JSON.stringify() ожидает объект JavaScript, массив, строку, число, логическое значение или значение NULL и сериализует его в строку, содержащую JSON.Тип возвращаемого значения - строка.Это операция «закодировать», «сериализовать» или «преобразовать в JSON».

JSON.parse() ожидает объект JSON, то есть строковую переменную, содержащую JSON, и преобразует его обратно в объект JavaScript,массив, строка, число, логическое значение или ноль.Тип возвращаемого значения зависит от того, что было преобразовано в строку JSON на самом внешнем уровне.Это операция «декодирования», «десериализации» или «из JSON».Если какие-либо строки в объекте JSON содержат JSON, декодирование не является рекурсивным.Они декодируются как строки, а не как объекты внутри, поэтому для получения доступа к объекту внутри как к объекту JavaScript необходим дополнительный слой JSON.parse() к полученным строкам.

...