Aws-lambda-dotnet: Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer使用与Amazon.Lambda.Serialization.Json.JsonSerializer不同的属性框

创建于 2020-04-15  ·  43评论  ·  资料来源: aws/aws-lambda-dotnet

似乎默认的大小写行为已在Amazon.Lambda.Serialization.Json.JsonSerializerAmazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer

这是一些示例代码测试区别:

// create an instance to serialize
var record = new Record {
    Foo = "Hello world!"
};

// show serialization with original Lambda serializer based on Newtonsoft.Json
var oldSerializer = SerializeWith(record, new Amazon.Lambda.Serialization.Json.JsonSerializer());
Console.WriteLine($"Amazon.Lambda.Serialization.Json.JsonSerializer: {oldSerializer}");

// show serialization with new Lambda serializer based on System.Text.Json
var newSerializer = SerializeWith(record, new Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer());
Console.WriteLine($"Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer: {newSerializer}");

// show serialization with System.Json.Text
var jsonTextSerializer = System.Text.Json.JsonSerializer.Serialize<Record>(record);
Console.WriteLine($"System.Text.Json.JsonSerializer: {jsonTextSerializer}");

// local functions
string SerializeWith<T>(T value, Amazon.Lambda.Core.ILambdaSerializer serializer) {
    using var buffer = new MemoryStream();
    serializer.Serialize<T>(value, buffer);;
    return System.Text.Encoding.UTF8.GetString(buffer.ToArray());
}

上面的代码产生以下输出:

Amazon.Lambda.Serialization.Json.JsonSerializer: {"Foo":"Hello world!"}
Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer: {"foo":"Hello world!"}
System.Text.Json.JsonSerializer: {"Foo":"Hello world!"}

最有用的评论

是否可以将这个问题保留在主题中?

所有43条评论

同意我不应该在2个库之间切换大小写。 我认为我们缺少针对自定义请求和响应的测试,因为这些测试现在主要集中在AWS事件上。

现在已经提供了更改默认行为的方法,这实际上是不可行的。 我的建议是添加一个新的构造函数,该构造函数采用用于枚举样式的枚举,以便您可以声明要使用的枚举。 然后,我可以更新模板以使用新的构造函数。 您对周围的环境有何看法?

我不知道这里的想法是什么。 我知道您不想破坏可能已经依赖的人。 似乎错误是相信AWS在JSON字段的命名方面具有一致性(即AWSNamingPolicy )。 它不是。 某些服务使用Pascal框,例如CloudFormation:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html

恕我直言,自动更改大小写而不遵守默认的System.Text.Json行为是一个致命缺陷。 也许考虑释放Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializerV2并将旧的放到冰上。

为了澄清,因为我不熟悉它的工作原理,所以程序集属性声明仅用于反序列化,对吗?

[assembly: LambdaSerializer(typeof(Amazon.Lambda.SystemTextJson.LambdaJsonSerializer))]

但是,如果使用此处理程序签名,是否甚至需要它?

Task<Stream> FunctionHandlerAsync(Stream stream, ILambdaContext context)

如果没有针对汇编或入口点方法的LambdaSerializerAttribute声明,该怎么办?

@normj一个选项可能是添加属性以显式命名json属性,因此无论大小写如何都遵循命名

我同意这一建议-添加它们是一项繁琐的一次性工作,但是它们始终是正确的。

@normj恕我直言,这是一个实现问题,需要/应作为BUG进行长期解决,因为这是意外的BREAKING CHANGE

@ 3GDXC我同意这是一个实现错误。 只是思考解决方案。 当前,在程序包中,我们有一个名为LambdaJsonSerializer序列化器。 如果我们添加从LambdaJsonSerializer扩展的PascalCaseLambdaJsonSerializerCamelCaseLambdaJsonSerializer序列化器怎么办? 我可以更改模板以使用PascalCaseLambdaJsonSerializer来保留现有行为。 这是@bjorg建议使用LambdaJsonSerializerV2的更明确的版本。

@normj恕我直言,最好避免混淆,将JsonPropertyName属性添加到消息中,以便无论序列化程序配置/选项如何,最终的Json都遵循属性命名。

我完全理解为什么您不愿意在发布.NET 3.1支持后的几天内(进行更正)进行进一步的重大更改; 如果我们(皇家)遇到了许多UP-FOR-GRABS问题,那么社区就无法进行单元/回归测试,就可以帮助他们在发布之前进行实施和测试。

很高兴为您提供帮助,如果需要时,只需说一句话即可。

迄今为止的出色工作,很高兴看到aws lamba和.net核心支持不断增长

@ 3GDXC请记住,大小写只影响我们必须从.NET对象转到JSON字符串的返回对象。 在我们提供的几个响应对象中,我确实使用了JsonPropertyName,下面是一个示例: https :

问题是其他人在我无法控制他们是否使用JsonPropertyName属性的地方创建的响应对象。

@normj好点; 可能是建议,也应包括始终使用JsonPropertyName属性来强制对属性和/或数据合同进行明确命名(最佳做法)

@normj一种替代方法可能是将JsonSerializerOptions抽象化为LambdaSerializerOptions类,并将这些选项作为构造函数参数添加到属性中,以便序列化程序可以具有开发人员可以在程序集/方法级别覆盖的自定义选项

将其标记为回归并将其固定为重大更改而不是传播更多危害,该怎么办? 我称它为_harm_,因为基于System.Text.Json LambdaJsonSerializer不遵守如何序列化属性的默认行为。 当然,使用[JsonPropertyName]解决此问题,但是要求每个人都采取措施来应对有害行为似乎是沉重的负担。

当采用LambdaJsonSerializer作为标准序列化程序时,有多少人会继续遇到__ !!?!?_这个?

嗨,我在将Lambda任务切换到.Net 3.1 +新的序列化程序之后,在“步骤函数”中遇到了此问题。 因为现在的输出是驼峰式的,所以这造成了严重破坏,因此下一个状态机形状将尝试使用Amazon States Language评估新的JSON并抛出Step Function异常。

目前有一种解决方法。 通过在环境变量中设置LAMBDA_NET_SERIALIZER_DEBUG=true ,就不会在序列化程序中设置_.options ,从而使原封不动地返回。 我不确定这是否会导致其他后果,而不是将其他JSON发送到Cloudwatch日志中。
https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Serialization.SystemTextJson/LambdaJsonSerializer.cs#L69 -L90

IMO,用[JsonPropertyName]装饰我们的所有模型会很痛苦,因为我们的模型埋在许多nuget库中。 理想情况下,我希望默认行为能够像以前一样返回到原始的PascalCasing,但我可以在我们的Step Function项目中调用带有lambda的显式PascalCaseLambdaJsonSerializer时很好。

谢谢!

我很确定,kludgy解决方法是一个错误。

关于上游程序集定义的数据结构的要点。

我不知道如果没有[JsonPropertyName]属性,它将对其他事物产生什么副作用,但是使用LambdaJsonSerializer构造函数可以自定义JSON序列化程序,可以通过以下方式恢复为默认的PascalCase行为:将JsonSerializerOptions.PropertyNamingPolicynull

链接到问题628,因为它与本次讨论有关。

我认为这是相关的。

查看APIGatewayProxyRequest.cs ,我注意到没有[JsonPropertyName]批注。 起作用的唯一原因是:a) LambdaJsonSerializer默认为不区分大小写的反序列化,以及b) LambdaJsonSerializer在序列化时使用骆驼框。

我可以看到它为注释各种帮助程序集中的所有请求/响应类节省了很多时间,但这意味着当我们使用帮助程序集时,必须在函数中使用LambdaJsonSerializer

事后看来,将[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]批注放在函数处理程序使用的POCO类上而不是函数类本身上更有意义吗? 看来,该函数最终必须使用与请求/响应类匹配的序列化程序。

@bjorg IMO POCO是关于要使用的序列化的属性元数据的错误位置; POCO仅应关注其域,即模型验证属性和属性类型/命名; 序列化应该尊重/使用这些模型注释。

恕我直言,应该更改LambdaSerializer属性以接受序列化的类型,例如。 Amazon.Lambda.Serialization.Json.JsonSerializer,带有可选的序列化选项; 如果未提供该选项,则将使用默认和兼容设置。

但是POCO需要使用正确的序列化程序属性进行注释:Newtonsoft为[JsonProperty] [JsonPropertyName] ,System.Text.Json为

它看起来像[DataMember]将均能够支持Newtonsoft.JsonSystem.Text.Json 。 但是,直到.NET 5才使用后者。 :(
https://github.com/dotnet/runtime/issues/29975

同时,一种解决方案是用[DataMember][JsonPropertyName]注释所有POCO。 这两个属性都是在.NET Core 3.1中定义的,因此不需要其他外部依赖项。

这样是否不能确保所有类的序列化/反序列化(至少对于属性名称)一致? 转换器需要通过ILambdaSerialize实现进行注册。

此处的链接问题已关闭。 从略读中我的理解是线程不打算支持该线程: https :

是的我看错了我看到了5.0链接并跳到错误的结论。

我发布了PR https://github.com/aws/aws-lambda-dotnet/pull/636解决了这个问题。 我们希望能提供反馈,或者最好还是从PR中的链接下载预览版本,并帮助您验证所做的更改。

首先,感谢您这么快解决这个问题。 对不起,它毁了你的星期六。

乍一看,它看起来不错。 我目前正在剔除所有Newtonsoft.Json引用,但是不幸的是,我目前无法验证该修复程序。 现在,我只复制了有问题的序列化器类,并删除了有问题的语句。 希望到明天EOD,我可以在我的dev分支中测试此更改。

首先想到的可能是缺少注释。 是否有任何不使用[DataMember]而是依赖于隐式骆驼套的响应数据结构?

@bjorg不用担心。 经过一周的会议,编写文档并帮助孩子们上学,有一些安静的时间并做一些星期六的编码,这让我感到非常安慰。

使用Newtonsoft序列化程序,我们可能会丢失[DataMember]批注。 我不太担心,因为对于已知类型,我们确实对其进行了测试。 在这种情况下,我的空白是缺少对自定义响应的测试。

可以释放-rc1吗? 另一种选择是AFAIK,否则对我来说会启用正确的编译常量,对_.csproj_文件进行黑客攻击。 还有另一种方法吗?

@bjorg在PR中,有一个指向包含预建NuGet软件包的zip文件的链接,您可以设置本地NuGet源并将其放在其中吗?

今天学到了一些新东西:如何拥有本地供稿。 事实证明,在.NET Core中超级简单(请参阅SO文章)。

我最相关的反馈是将_options公开Options受保护/公共

否则,从我这一方面来说,使用此新代码的一切都很好。 谢谢!

@normj让我知道是否/何时有更新的nuget软件包。 很高兴再次进行测试。

https://github.com/aws/aws-lambda-dotnet/issues/544#issuecomment -567780775

^是因为不使用骆驼套会破坏API网关吗?

如果lambda在ALB上,但Cos Pascal可以正常工作,但在API Gateway上却不能工作,这种不一致令人困惑。 在移到system.text之前,这是如何工作的?

这是一个重大变化。 接口不兼容。 由于缺乏集成测试和/或候选发布社区审核,因此违反了接口隔离原则。 无法解决的时间越长,这将给AWS客户造成更大的成本和浪费的工时,从而对AWS声誉产生影响。

我建议您将其标记为已发布,并建议所有开发人员不要迁移至3.1,直到达成一致。
此外,我还建议社区讨论并全面测试所有修复程序,以减少进一步加剧该问题的可能性

@lukebrowell串行https://github.com/aws/aws-lambda-dotnet/pull/568 PR附带了一个预构建的程序包,用于测试可以通过自定义Lambda运行时完成的测试。

我们正在与PR一起讨论此修复程序,我欢迎对建议的修复程序提供反馈https://github.com/aws/aws-lambda-dotnet/pull/636

我同意这是一个重大的变化,但我对此感到失望,但对于您建议的严重性我不同意。 该问题仅影响返回自定义响应的Lambda函数,而不是所有Lambda函数以及现有的Amazon.Lambda.Serialization.Json都可以正常工作,因此我不敢肯定地说整个3.1 Lambda版本已损坏。 但是,我再次理解了这种挫败感,对不起这个错误漏了。

我希望下周早些时候在PR中进行更改,除非收到有关该更改的任何重大反馈而导致发布延迟。

@bjorg PR已更新,其中包含指向预构建软件包的preview2的链接。 https://normj-packages.s3.us-west-2.amazonaws.com/rework-serialization-preview2.zip

@normj我意识到社区对此负有部分责任,因为(我们)施加了作为正式lambda映像发布/支持.netcore 3.1运行时的压力,并且没有报告或提供反馈。 恕我直言,虽然我了解您对@lukebrowell的看法,但我会部分同意@lukebrowell的建议,并建议启动一个工作单元(在社区的充分参与下),以展开有关aspnetcore lambda函数/服务库的功能/设计的讨论。旨在解决在庄园中发现的任何缺陷和/或错误,这些缺陷和/或错误会有助于开发的向前发展,因为该软件包感觉有些急事TBH。

我希望看到一个更强大的社区。 我一直在awsdevelopers.slack.com上闲逛,但是#dotnet频道有点安静。 Lambda .NET Core核心人员聚集在另一个地方吗?

@bjorg我将加入;)在那见(实际上)

@bjorg可以得到邀请吗?

从主持人那里获取邀请链接。 会在这里发布。

是否可以将这个问题保留在主题中?

同意,让我们继续关注这个话题。 我创建了一个社区问题#647,内容涉及如何联系我以将您添加到AWS松弛小组。

是的,我欢迎有关如何更好地建立社区沟通以及我在哪里可以更好地进行自己的沟通以及如何参与其中的建议。

_preview2_对我来说不错。

Amazon.Lambda.Serialization.SystemTextJson的版本2.0.0随更改而发布。 主要解决方法是将序列化程序类更新为DefaultLambdaJsonSerializer

我还发布了一篇博客文章,其中包含描述更改的部分。
https://aws.amazon.com/blogs/developer/one-month-update-to-net-core-3-1-lambda/

此页面是否有帮助?
0 / 5 - 0 等级