質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

Slack

Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

3902閲覧

AWS LambdaのNode.jsとJSONについて

HiroakiKamei

総合スコア8

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

Slack

Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2018/02/05 09:14

編集2018/02/05 09:15

はじめまして、Node.js初心者です。
前回に続き、GoogleHomeからSlackに投稿したいです。

前提・実現したいこと

GoogleHome→Dialogflow→APIGateway→AWSLambda→Slack

参考にしたサイト様
Dialogflow入門
AWS API Gateway+LambdaでSlackにメッセージをPOSTする(前編)
Google Home と Lambda で「"あ"のつくポケモンなーんだ」

DialogflowのFulfillmentでAPIGatewayをあてており、
Lambdaでこのコードを入れたところエラーがでます。
Dialogflow側では問題なくJSONが送られている状態です。

発生している問題・エラーメッセージ

{ "errorMessage": "RequestId: f396756f-0a52-11e8-967f-79dda54dff68 Process exited before completing request" }

該当のソースコード

JavaScript

1console.log('Loading function'); 2 3const https = require('https'); 4const url = require('url'); 5const slack_url = process.env.SLACK_WEBHOOK_URL; 6const slack_req_opts = url.parse(slack_url); 7slack_req_opts.method = 'POST'; 8slack_req_opts.headers = {'Content-Type': 'application/json'}; 9 10exports.handler = function(event, context, callback) { 11 if (!event.text) { 12 callback('called without event.text'); 13 return; 14 } 15 var req = https.request(slack_req_opts, function (res) { 16 if (res.statusCode === 200) { 17 callback(null, 'posted to slack'); 18 } else { 19 callback('status code: ' + res.statusCode); 20 } 21 }); 22 23 req.on('error', function(e) { 24 console.log('problem with request: ' + e.message); 25 context.fail(e.message); 26 }); 27 28 // メッセージの編集 29 const parameters = JSON.parse(event.body).result.parameters; 30 var message = parameters.date + parameters.building + parameters.request; 31 var slack_text = message; 32 33 req.write(JSON.stringify({text: slack_text})); 34 35 req.end(); 36}; 37 38

試したこと

上記の部分を下記に変更すれば問題なく動くのですが、ただ単にLambdaのテストで設定したテキストがSlackに送られる状況です。

JavaScript

1 // メッセージの編集 2 const parameters = JSON.parse(event.body).result.parameters; 3 var message = parameters.date + parameters.building + parameters.request; 4 var slack_text = message;

JavaScript

1 // メッセージの編集 2 var message = (event.text); 3 var slack_text = message;

補足情報

エラーコードをググって見たところ、処理が途中で終了してしまうと発生してしまうようで、
CloudWatchからエラーを探ったところ、

SyntaxError: Unexpected token u in JSON at position 0 at Object.parse (native) at exports.handler (/var/task/index.js:29:29)

とでています。調べると
Uncaught Syntaxerror: Unexpected token u

コールバックと引数が一致していない?のでしょうか
ここからハマってしまいわからない状況です。

ご回答ご教授願います、よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

SyntaxError: Unexpected token u in JSON at position 0
コールバックと引数が一致していない?のでしょうか

いいえ。JSON.parseしようとしたevent.bodyがundefinedだった可能性が高いです。例えば以下のコードで同様のエラーが得られます。

javascript

1const data = {}; 2JSON.parse(data.foo);

JSON.parseは渡されたJSONの文字列の先頭が{なら「Objectかな…」[なら「Arrayかな…」、1なら「Numberかな…」、と解析できますが、undefinedだと「先頭uなの!?」となって、結局

SyntaxError: Unexpected token u in JSON at position 0

とエラーを出して止まります。

エラーを先まで見ると、どこで止まったかが書いてあります。
イメージ説明
スクリプトの29行目の29文字目でエラーになったようです。スクリプトの29行目を確認しましょう。

javascript

1 // メッセージの編集 2 const parameters = JSON.parse(event.body).result.parameters;

JSON.parseのところだと分かります。このことから、event.bodyが変で、JSONの文字列が渡らなかったのかな、と予想できます。なので、原因を調べるために、以下のように1行追加して、もう一度テストしてみてください。困ったときは、おかしい行の前でconsole.logすれば、たいていの問題は原因がわかります。

// メッセージの編集 console.log(event); // 追加 const parameters = JSON.parse(event.body).result.parameters;

今回の場合、API Gatewayからのアクセス、つまり、HTTPのリクエストがトリガーとなります。このときのeventオブジェクトには、HTTPのヘッダの情報やアクセス元の情報が入っていて、Lambdaのコンソールからテストしたときのような、単純な構造にはなっていません。

Lambdaのコンソールには、API Gatewayからのeventオブジェクトっぽいものでテストするサンプルがありますので、それを使いましょう。

テストイベントの設定から、
イメージ説明

API Gateway AWS Proxyを選び、
イメージ説明

2行目のbodyにJSONを書いてテストしてください。
イメージ説明

ここが問題なければ、AWSLambda → Slackは問題ありません。
次はAPIGatewayのコンソールからAPIGateway → AWSLambdaをテストしましょう。

イメージ説明

リクエスト本文にJSONを書いてテストしてください。

ここが問題なければ、APIGateway → AWSLambdaも問題ありません。
次はDialogflow → APIGatewayを確認することになりますが、長くなったので回答はここまでとします。

投稿2018/02/05 13:05

編集2018/02/05 17:10
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HiroakiKamei

2018/02/08 02:35 編集

こんにちは、前回に引き続き丁寧な解説とご迅速な回答ありがとうございます....!! こちらの返答が遅れてしまいすみません。 ご指摘があったようにLambdaのテストのところにAPIgatewayをあて、 bodyに内容をいれたところエラーがでました。 SyntaxError: Unexpected token o in JSON at position 1 at Object.parse (native) at exports.handler (/var/task/index.js:30:29) u→o でオブジェクトになっているとのエラーだと思うのですが、 テストコードのJSONの書き方がわるいのでしょうか? { "text": "Posted Slack", "body": { "result": { "parameters": { "request": "出社", "date": "2018-02-06", "building": "本社", "place": "東京", "time": "08:30:00" } } }, "resource": "/{proxy+}", "requestContext": { "resourceId": "123456", "apiId": "1234567890", "resourcePath": "/{proxy+}", //以下略 よろしくお願いします。
退会済みユーザー

退会済みユーザー

2018/02/07 01:47

3枚目の画像の2行目のところを見てください。bodyはHTTPのリクエストのbodyで、文字列で指定します。したがって、{foo: 'bar'}を送るには、"{\"foo\": \"bar\"}"のようにJSONをJSONの中に書かないといけません。面倒な場合は、ブラウザのコンソールなどでJSON.stringify(JSON.stringify({foo: 'bar'}))とするといいです。
HiroakiKamei

2018/02/07 09:03

回答ありがとうございます、無事AWSLambda → Slackへ送れました!! 引き続きAPIGatewayでテストしてみようと思います、ありがとうございます。
HiroakiKamei

2018/02/07 10:03

度々すいません、APIGatewayで実際にDialogflowから流れてくるJSONを入れたところエラーが出てしまいます... "errorMessage": "RequestId: bcfe69c8-0beb-11e8-8ad0-dfc413bf363b Process exited before completing request" } レスポンスヘッダー {"X-Amzn-Trace-Id":"sampled=0;root=1-5a7acae7-40080432fcbeae52d359a94b","Content-Type":"application/json"]
退会済みユーザー

退会済みユーザー

2018/02/07 11:06

Lambdaはうまくいったようでよかったです。API Gatewayのエラーについては (1) まず、Lambdaのログにもエラーがででいるはずですので、確認してみてください。 (2) API Gatewayでテストするときのリクエスト本文を確認してみてください。ここは、JSONのJSONではなく、JSONで大丈夫です。{"body": "hello"} のような感じです。原因はおそらくここじゃないかと思っています。
HiroakiKamei

2018/02/08 02:34 編集

おはようございます、ご返信ありがとうございます。 (1)Lambda側では SyntaxError: Unexpected token o in JSON at position 1 とでています。APIGatewayでは(2)で仰られたように { "text": "Posted Slack", "body": { "result": { "parameters": { "request": "出社", "date": "2018-02-06", "building": "本社", "place": "東京", "time": "08:30:00" } } } を入れて実行しています...
退会済みユーザー

退会済みユーザー

2018/02/08 06:20

console.log(event) は書いてありますか? Lambdaでエラーが検知できたということは、console.logで原因がわかるはずですので、console.log(event)して、event.bodyとしてどんなものが渡ってきたのかを確認してください。 console.log(event) は完成するまで残しておいて、何かあったらすぐに確認できようにしておくといいです。 別件ですが、そのテストデータだと、 JSON.parse(event.body).result.parameters が取れません。 {"text": ..., "body": {"result": ...}} ではなくて、 {"result": ...} が正しいのではないでしょうか。逆に、そのテストデータが正しいなら、Lambdaの方を修正する必要がありますね。
HiroakiKamei

2018/02/13 03:31

おはようございます、コメントありがとうございます。 返信が遅れてしまいましてすいません。 console.log(event)で渡ってきたものは { result: { parameters: { request: '出社', date: '2018-02-06', building: '本社', place: '東京', time: '08:30:00' } } } で、(ご指摘があったのでテストデータを{"result": ...}に変更しました) その後に続くエラーが SyntaxError: Unexpected token u in JSON at position 0 at Object.parse (native) at exports.handler (/var/task/index.js:30:29) となっています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問