【问题标题】:Serverless Framework and DynamoDB: Unexpected token in JSON at JSON.parse无服务器框架和 DynamoDB:JSON.parse 中 JSON 中的意外令牌
【发布时间】:2020-01-20 02:20:38
【问题描述】:

您好,我关注了这个Serverless + AWS REST API tutorial,它做得很好,我让它工作了。

现在,我正在尝试修改它,但在尝试将数据提交到 DynamoDB 表时遇到了困难。

使用 Postman 提交一个有效的 JSON 对象,我得到一个 502 响应。如果我在 Lambda 中测试函数,我会收到以下错误:

{
  "errorType": "SyntaxError",
  "errorMessage": "Unexpected token o in JSON at position 1",
  "trace": [
    "SyntaxError: Unexpected token o in JSON at position 1",
    "    at JSON.parse (<anonymous>)",
    "    at Runtime.module.exports.submit [as handler] (/var/task/api/interview.js:11:28)",
    "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)",
    "    at process._tickCallback (internal/process/next_tick.js:68:7)"
  ]
}

在搜索解决方案后,我发现似乎以JSON.parse(event) 传递的event 未定义。

这是 serverless.yml:

service: interview

frameworkVersion: ">=1.1.0 <2.0.0"

provider:
  name: aws
  runtime: nodejs10.x
  stage: dev
  region: us-east-1
  environment:
    INTERVIEW_TABLE: ${self:service}-${opt:stage, self:provider.stage}
    INTERVIEW_EMAIL_TABLE: "interview-email-${opt:stage, self:provider.stage}"
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
      Resource: "*"

resources:
  Resources:
    CandidatesDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          -
            AttributeName: "id"
            AttributeType: "S"   
        KeySchema:
          -
            AttributeName: "id"
            KeyType: "HASH"
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        StreamSpecification:
          StreamViewType: "NEW_AND_OLD_IMAGES"
        TableName: ${self:provider.environment.INTERVIEW_TABLE}

functions:
  interviewSubmission:
    handler: api/interview.submit
    memorySize: 128
    description: Submit interview information and starts interview process.
    events:
      - http: 
          path: interviews
          method: post

和 interview.js

'use strict';

const uuid = require('uuid');
const AWS = require('aws-sdk'); 

AWS.config.setPromisesDependency(require('bluebird'));

const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.submit = (event, context, callback) => {
  const requestBody = JSON.parse(event);
  const fullname = requestBody.fullname;
  const email = requestBody.email;
  const test = requestBody.test;
  const experience = requestBody.experience;

  if (typeof fullname !== 'string' || typeof email !== 'string' || typeof experience !== 'number') {
    console.error('Validation Failed');
    callback(new Error('Couldn\'t submit interview because of validation errors.'));
    return;
  }

  submitInterviewP(interviewInfo(fullname, email, experience, test))
    .then(res => {
      callback(null, {
        statusCode: 200,
        body: JSON.stringify({
          message: `Sucessfully submitted interview with email ${email}`,
          interviewId: res.id
        })
      });
    })
    .catch(err => {
      console.log(err);
      callback(null, {
        statusCode: 500,
        body: JSON.stringify({
          message: `Unable to submit interview with email ${email}`
        })
      })
    });
};


const submitInterviewP = interview => {
  console.log('Submitting interview');
  const interviewInfo = {
    TableName: process.env.INTERVIEW_TABLE,
    Item: interview,
  };
  return dynamoDb.put(interviewInfo).promise()
    .then(res => interview);
};

const interviewInfo = (fullname, email, experience,test) => {
  const timestamp = new Date().getTime();
  return {
    id: uuid.v1(),
    fullname: fullname,
    email: email,
    experience: experience,
    test: test,
    submittedAt: timestamp,
    updatedAt: timestamp,
  };
};

如果我将 event 参数替换为有效的 JSON 对象,然后再次部署。我能够成功地将对象插入 dynamoDB。

有什么线索吗?请让我知道是否有任何我遗漏的东西可以提供帮助。

谢谢!

【问题讨论】:

  • 在 yml 的第 11 行放置单反引号而不是双引号。
  • INTERVIEW_EMAIL_TABLE: 'interview-email-${opt:stage, self:provider.stage}'?什么都没做!有什么想法吗?

标签: rest aws-lambda amazon-dynamodb serverless-framework aws-serverless


【解决方案1】:

API Gateway 在事件的 body 属性中对请求正文进行字符串化。

当前您正在尝试解析错误的事件对象const requestBody = JSON.parse(event);。你需要解析 event.body 属性:

const requestBody = JSON.parse(event.body);

【讨论】:

  • 那也没用。错误略有变化`“位置 0 处 JSON 中的意外标记 u”` 以前说的是 '...token o...',现在说的是 '...token u...'
  • 您的请求对象是什么样的?你能告诉我们有效载荷吗?
  • 好吧,由于某种原因,当我从 Postman 执行 POST 时,POST 可以工作,但 Lambda 测试失败并出现同样的错误……我成功地将这个对象 {"fullname":"Fran","email": "ffff@gmail.com", "experience":1.5, "test": 123} 发布到 dynamodb。我也可以从浏览器、邮递员或 lambda 获取所有对象。在邮递员中,我发送标准参数:Content-Type:application/json。这是你要问的吗?
  • 如果您从 Lambda 控制台测试它,那么事件就是您在“测试配置”中放入的内容。如果您将数据发布到 API 网关端点,那么您的数据将在 event.body 中进行字符串化。
  • 将第 11 行更改为 const requestBody = event.body ? JSON.parse(event.body) : event;
猜你喜欢
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 2016-08-20
  • 1970-01-01
  • 2017-09-27
相关资源
最近更新 更多