作为将运行在 EC2 上的一些现有 .NET Core 3.0 工作服务迁移到 AWS Lambda 的一部分,我们编写了一个自定义ILambdaSerializer
实现来处理反序列化负载到 Lambda 函数,例如SQSEvent
.
虽然这相对简单,但如果 System.Text.Json 的序列化程序实现内置到 Lambda SDK 中以节省跨不同函数代码库的复制粘贴需求,那就太好了。
迄今为止,状态的一个缺点是PropertyNameCaseInsensitive
必须在序列化程序选项上设置为true
,因为事件不使用一致的 PascalCase 与 camelCase 命名,这会导致性能损失(我没有量词来说明损失的多少)。 在SQSEvent
的情况下,我相信是eventSourceARN
绊倒了它,因为它没有映射到EventSourceArn
。
我想这可以通过在模型的属性中添加[JsonPropertyName("...")]
属性注释来轻松地在事件库中修复。
我相信,如果接口上有异步方法来利用System.Text.Json.JsonSerializer
的异步支持并直接使用Stream
,则可以获得更多好处,但这是一个更大的变化,仅提供基于当前界面。
下面是我们正在使用的代码。 它可能会从进一步的优化中受益,但现在它对我们来说效果很好:
using System.IO;
using System.Text.Json;
using Amazon.Lambda.Core;
namespace MyLambdaFunction
{
public sealed class SystemTextJsonLambdaSerializer : ILambdaSerializer
{
private readonly JsonSerializerOptions _options;
public SystemTextJsonLambdaSerializer()
{
// SQSEvent does not use a consistent camel/Pascal case naming convention,
// so as we cannot annotate with attributes, the options need to be case
// insensitive to be tolerant for things to work properly when deserializing.
_options = new JsonSerializerOptions()
{
IgnoreNullValues = true,
PropertyNameCaseInsensitive = true,
};
}
public T Deserialize<T>(Stream requestStream)
{
using var copy = new MemoryStream();
requestStream.CopyTo(copy);
byte[] utf8Json = copy.ToArray();
return JsonSerializer.Deserialize<T>(utf8Json, _options);
}
public void Serialize<T>(T response, Stream responseStream)
{
using var writer = new Utf8JsonWriter(responseStream);
JsonSerializer.Serialize(writer, response, _options);
}
}
}
/cc @normj
谢谢@martincostello。 我将把它移到我们的 Lambda .NET 存储库中。
请注意, @martincostello 不适用于 API Gateway。
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
您也需要添加它,否则由于属性上的帕斯卡大小写,响应将被视为格式错误。
谢谢@phillip-haydon,这很有帮助。
我一直在system.text.json分支中为此提供官方支持。
我正在通过现有的事件测试来确保新的序列化程序与 Newtonsoft 的工作方式相同。 它仍然是一项正在进行的工作,但请随时查看并提供反馈。
已创建此 PR,其中包含指向 NuGet 包的一些预览版本的链接,供当前正在试用 .NET Core 3.1 和 Lambda 自定义运行时功能的用户使用。 https://github.com/aws/aws-lambda-dotnet/pull/568。
我将关闭此问题并使用 PR 来跟踪此功能。
最有用的评论
谢谢@martincostello。 我将把它移到我们的 Lambda .NET 存储库中。