Search code examples
c#.net-coreaws-lambdaaws-step-functions

Pass Json string to AWS Lambda in Step Function - JsonReaderException error


I am attempting to use a AWS Lambda function in a Step Function. The Lambda Function works correctly when the it is tested individually and the json input is escaped. However when the input is passed to the lambda function through a step function, I am getting a JsonReaderException error. What am I doing wrong? Would the community know of a workaround for this issue?

lambda function:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization.Formatters.Binary;
using Amazon.Lambda.Core;
using Newtonsoft.Json.Linq;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
namespace AWSLambda1
{
    public class Function
    {
        public void PostsBasedOnOddOrEven(string input, ILambdaContext context)
        {
            var details = JObject.Parse(input);
            var postId = (int) details["id"];
            var oddOrEvenResult = (int) details["OddOrEvenPostsResult"];
        }
    }
}

Input to Lambda function from Step Function:

{
  "id": "1",
  "OddOrEvenPostsResult": 2
}

Input to Lambda function (which works through the Visual Studio Invoke):

"{ \"id\": \"1\", \"OddOrEvenPostsResult\": 2}"

Exception Stack Trace:

{
  "errorType": "JsonReaderException",
  "errorMessage": "Unexpected character encountered while parsing value: {. Path '', line 1, position 1.",
  "stackTrace": [
    "at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType)",
    "at Newtonsoft.Json.JsonTextReader.ReadAsString()",
    "at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter)",
    "at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)",
    "at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)",
    "at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)",
    "at Amazon.Lambda.Serialization.Json.JsonSerializer.Deserialize[T](Stream requestStream)",
    "at lambda_method(Closure , Stream , Stream , LambdaContextInternal )"
  ]
}

Lambda Function not working when it is part of Step Function

Lambda Function not working when it is part of Step Function

Lambda Function working when tested individually

Lambda Function working when tested individually


Solution

  • Since your lambda function is expecting input to be a string, the framework tries to parse the input as though it's a string.

    However, the input is actually a JSON object, not a string.

    Therefore the parser will fail with an "unexpected character" error. The parser is expecting a " character which would indicate the start of a string.


    So, here's how you can fix it:

    1. Declare a c# class which represents the input

      public class FunctionInput
      {
          public int id { get; set; }
          public int OddOrEvenPostsResult { get; set; }
      }
      
    2. Change your function signature to expect input of type FunctionInput

      public class Function
      {    
          public void PostsBasedOnOddOrEven(FunctionInput input, ILambdaContext context)
          {
              var postId = input.id;
              var oddOrEvenResult = input.OddOrEvenPostsResult;
          }
      }
      

    Note: you don't need to parse the input yourself.