Eric Snyder
Eric Snyder

Reputation: 1944

AWS Hello World C# Lambda function returning Json error

I am using the default AWS Visual Studio template. When I run the test locally and use the AWS Hello World Example Request:

enter image description here

I get the error:

System.Exception: Error deserializing the input JSON to type String at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.BuildParameters(ExecutionRequest request, ILambdaContext context) in C:\codebuild\tmp\output\src184553615\src\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 215 at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.ExecuteAsync(ExecutionRequest request) in C:\codebuild\tmp\output\src184553615\src\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 52 ---------------- Inner 1 Exception ------------ System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Amazon.Lambda.TestTool.Runtime.LambdaExecutor.BuildParameters(ExecutionRequest request, ILambdaContext context) in C:\codebuild\tmp\output\src184553615\src\Tools\LambdaTestTool\src\Amazon.Lambda.TestTool\Runtime\LambdaExecutor.cs:line 203 ---------------- Inner 2 Exception ------------ Amazon.Lambda.Serialization.SystemTextJson.JsonSerializerException: Error converting the Lambda event JSON payload to a string. JSON strings must be quoted, for example "Hello World" in order to be converted to a string: The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1. at Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer.Deserialize[T](Stream requestStream) ---------------- Inner 3 Exception ------------ System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1. at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex) at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack) at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader) at System.Text.Json.JsonSerializer.ParseCore(ReadOnlySpan1 utf8Json, Type returnType, JsonSerializerOptions options) at System.Text.Json.JsonSerializer.Deserialize[TValue](ReadOnlySpan1 utf8Json, JsonSerializerOptions options) at Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer.Deserialize[T](Stream requestStream) ---------------- Inner 4 Exception ------------ System.InvalidOperationException: Cannot get the value of a token type 'StartObject' as a string. at System.Text.Json.Utf8JsonReader.GetString() at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(ReadStack& state, Utf8JsonReader& reader) at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader) at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)

However, If I use "Hello World" as my input string it runs just fine. I definitely want to use Json for the input. I have validated the AWS Json input and it validates.

What am I doing wrong?

My code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace AWSLambda2
{
    public class Function
    {
        
        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public string FunctionHandler(String input, ILambdaContext context)
        {

            return input?.ToUpper();
        }
    }
}

The .csproj file contents:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>

    <!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="1.2.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.1.0" />
  </ItemGroup>
</Project>

Upvotes: 4

Views: 8299

Answers (1)

Kevin Hakanson
Kevin Hakanson

Reputation: 42230

The "Error deserializing the input JSON to type String" error message is because the method signature on your FunctionHandler specifies String but you testing with JSON.

public string FunctionHandler(String input, ILambdaContext context)

If you added code similar to below to define a class matching the structure of that input...

    public class FunctionInput
    {
        public string Key1 { get; set; }
        public string Key2 { get; set; }
        public string Key3 { get; set; }
    }

...then changed your method signature to specify FunctionInput...

public string FunctionHandler(FunctionInput input, ILambdaContext context)

...the LambdaSerializer would attempt to deserialized the JSON into that class.

Upvotes: 6

Related Questions