如何为System.Text.json.jsonserializer设置全球设置默认选项?
相反:
JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
// etc.
};
var so = JsonSerializer.Deserialize<SomeObject>(someJsonString, options);
我想做这样的事情:
// This property is a pleasant fiction
JsonSerializer.DefaultSettings = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
// etc.
};
// This uses my options
var soA = JsonSerializer.Deserialize<SomeObject>(someJsonString);
// And somewhere else in the same codebase...
// This also uses my options
var soB = JsonSerializer.Deserialize<SomeOtherObject>(someOtherJsonString);
希望不必为我们最常见的情况传递 JsonSerializerOptions 的实例,并覆盖异常,而不是规则。
如此问答中所示a,这是 Json.Net 的一个有用的功能。我查看了文档 对于 System.Text.Json
以及此 GitHub 存储库 对于 . NET 核心。还有这个 。
.NET Core 3 中似乎没有用于管理 JSON 序列化默认值的类似方法。或者我忽略了它?
-
更新 [2019-12-23]: 部分原因是声音 社区意见 此问题已已添加到 .NET 5.0 的路线图。
-
更新 [2019-10-10]: 如果有兴趣查看针对
System.Text 实现的此行为.Json.JsonSerializer
前往 由 Chris Yungmann 指出的开放式 GitHub 问题并参与.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
您可以创建一个扩展方法。 这是一个示例(更新 2023-10-27:将代码拉到底部这个答案是为了完整性)
我使用单独的方法而不是必须构建特殊的设置,以便所有设置都将位于一个位置并且易于重用。
然后,您可以将其作为字符串(无论是文字还是变量)的方法来调用。
更新于2023年10月27日
我重新审视了这个答案,并意识到示例代码从未包含在此处。我已将其复制到此处,以防链接代码发生问题。它最初针对 .NET Core 3.x,但最后确认是针对 .NET 7。
You can create an extension method. Here's an example (UPDATE 2023-10-27: Pulled the code to the bottom of this answer for completeness)
I use separate methods vs having to build special settings, so that all the settings will be in a single spot and easily reusable.
Then you call it as a method on a string, whether literal or a variable.
Updated 2023-10-27
I revisited this answer and realized that the example code was never included here. I have copied it here in case something happens to the linked code. It was originally targeting .NET Core 3.x but last confirmed with .NET 7.
这似乎对我有用,在 StartUp.ConfigureServices 中:
This seemed to work for me, in StartUp.ConfigureServices:
不,
JsonSerializerOptions
不会公开 默认选项。如果您使用特定的 Web 框架,可能有一种方法可以通过它指定(反)序列化设置。否则,我建议创建您自己的便捷方法。另请参阅此未决问题。
No,
JsonSerializerOptions
does not expose the default options. If you are using a particular web framework there may be a way to specify (de-)serialization settings through that. Otherwise, I suggest creating your own convenience methods.See also this open issue.
.NET Core 3.1 的
JsonSerializer
中未公开默认选项。不过,截至 2019 年 12 月,这已添加到路线图中对于 5.0。.NET 5.0 预计于 2020 年 11 月发布。但不能保证这个特定问题将在任何特定时间得到解决。除了等待之外,这些答案还建议了解决方法:
此外,受 @ps2goat 答案的启发,我打包了方便的扩展方法将它们放在 nuget.org 和 github:
The default options are not exposed in
JsonSerializer
for .NET Core 3.1. However, as of December, 2019 this has been added to the road map for 5.0.The release of .NET 5.0 is expected November, 2020. But there's no guarantee this particular issue will be addressed at any particular time. Other than waiting, these answers suggest workarounds:
Also, I packaged my convenience extension methods, inspired by @ps2goat's answer and put them on nuget.org and github:
a workaround> workaround> ://github.com/andre-ss6“ rel =“ nofollow noreferrer”> andre-ss6 如下:
update [2023-02-17] :但是有关net7 href =“ https://stackoverflow.com/a/74741382/1011722”>此答案。
A workaround has been proposed by GitHub user andre-ss6 as follows:
Update [2023-02-17]: but for NET7 see this answer.
使用.NET 8预发行,甚至包括蛇盒!
Using .NET 8 prerelease and it even includes snake case!
我寻找一种解决方案来使用源生成的上下文作为默认序列化器,但默认选项仍然是只读的。
我将其留在这里,以防对其他人有帮助: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source- Generation?pivots=dotnet-8-0#source- Generation-support- in-aspnet-core
那里的解决方案如下所示:
I looked for a solution to use my source generated context as the default serializer, but the default options are still read-only.
I'll just leave this here in case it helps someone else: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation?pivots=dotnet-8-0#source-generation-support-in-aspnet-core
The solution there looks like this:
一些田地已成为自动企业的开始.NET7。因此,无法像早期答案那样更改它。
新方法是直接更改私有字段:
为什么
getruntimefields()。单()
,而不仅仅是getruntimefield(%name%)
?答案在这里: https://github.com/dotnet/runtime/runtime/15643Some fields has became auto-properties starting .NET7. So there is no way to change it as in earlier answers.
New approach is to change the private fields directly:
Why
GetRuntimeFields().Single()
and not justGetRuntimeField(%name%)
? Answer is here: https://github.com/dotnet/runtime/issues/15643如果还需要将自定义转换器添加到默认的 JsonSerializerOptions (System.Text.Json >= 7.0.0) - 不使用控制器 - 可以使用以下技巧:
属性 JsonSerializerOptions.Default.Converters 不允许添加项目,因为它是不可变的,因此这个技巧完全取代了转换器列表。由于 ConverterList 是一个私有密封类,调用其构造函数需要反射。
In case one also needs to add custom converters to the default JsonSerializerOptions (System.Text.Json >= 7.0.0) - without the use of controllers - one can use the following trick:
The property JsonSerializerOptions.Default.Converters does not allow adding items, as is is immutable, therefore this trick replaces the converterList alltogether. And since ConverterList is a private sealed class invoking its constructor requires reflection.
正如 @elijah 评论的那样,注入
IOptions
jsonOptions 对我有用。然后我就可以使用 JsonSerializerOptions 属性。我注意到这与我在 Program.cs 文件中使用AddJsonOptions()
配置的内容没有区别。As @elijah commented, injecting
IOptions<JsonOptions>
jsonOptions worked for me. I was then able to use theJsonSerializerOptions
property. I noticed no differences between this and what I had configured usingAddJsonOptions()
in my Program.cs file.对于 ASP.NET Core 7.0+:
方法
HttpJsonServiceExtensions.ConfigureHttpJsonOptions()
:此方法可从 ASP.NET Core 7.0。
For ASP.NET Core 7.0+:
The method
HttpJsonServiceExtensions.ConfigureHttpJsonOptions()
:This method is available starting from ASP.NET Core 7.0.
我必须在HTTP客户端中使用其他转换器进行枚举。就我而言,避免在每个JSON转换中使用选项,并且由于没有选择默认选项的选项(除非使用上述反射)。我创建了一个转换器,并将其用作枚举上方的属性
:
I had to use a different converter for enums in my http client. In my case to avoid using the options in each json conversion, and due to not having the option to change the default options (unless using reflection from above). I created a converter and used it as attribute above the enum
Enum:
基于 @elijah关于注册
ioptions
的建议,这是一个完整的解决方案,它显示了如何在全球范围内正确配置和使用JSON Serialization选项。解决方案
首先,在
program.cs
中配置选项:这是针对
MINIAMAPI的
MVC,然后在您的服务中注入并使用这些选项。如果您需要在constructor中排放。
Based on @Elijah's suggestion about registering
IOptions
, here's a complete solution that shows how to properly configure and use JSON serialization options globally.Solution
First, configure the options in
Program.cs
:That's for MVC
That's for miniamApi
Then inject and use these options in your services.If you need you can ovveride in constructor.:
发现这个寻找一些灵感。我们有一个 Web API 可以调用其他一些 API。第三方 API 可能使用驼峰命名法,也可能使用 kebab 命名法。一般来说,每个 API 内部都是一致的,但 API 之间的命名约定会发生变化。我需要在有限的范围内配置选项,但不能污染其他项目。
我最终创建了一个选项对象,这样命名是为了不与设置混淆,特定于每个项目(将可见性设置为内部),通过 DI 呈现,该对象将 JSON 设置作为属性。特定于项目的设置(例如任意 API 如何命名属性)包含在该项目中,并且每个项目负责设置其默认值。
我发现,特别是对于库代码来说,具体并处理传递选项对象比尝试设置完整的应用程序默认值只是为了限制互操作性更好。这也让我可以避免在 DTO 上标记属性名称,因此我可以从顶级 API 序列化 DTO 出站,并且不会有违反 API 级约定的显式 JSON 属性名称。
如果您确实必须支持非典型的特定于属性的名称,则可以对公共未修饰属性使用带有 getter 和 setter 的内部属性来隔离更改。
Found this looking for some inspiration. We have a web API that calls some other APIs. The third-party APIs may use camel casing names, or they may use kebab. Generally, each is internally consistent with itself, but the naming convention changes between APIs. I needed to configure the options in a limited scope but not contaminate other projects.
I ended up making an options object, called such not to confuse with settings, specific to each project (set visibility to internal), surfaced through DI, that had the JSON settings as a property. Project-specific settings, like how an arbitrary API names properties, are contained to that project, and each project is responsible for setting its defaults.
I've found it's better, especially for library code, to be specific and deal with passing around the options object than to try and set up full app defaults only to limit interoperability. This also lets me avoid marking property names on my DTOs, so I can serialize the DTO outbound from my top-level API and not have explicit JSON property names breaking the API-level conventions.
If you do have to support an atypical property-specific name, you can use an internal property with getters and setters to your public undecorated property to isolate the change.
(如果您切换到使用 Json.NET)
我更喜欢并建议明确并将设置传递给所有调用,但您可以使用 DefaultSettings。
进而
(If you ever switch to using Json.NET)
I prefer and recommend being explicit and pass settings to all calls, but you can set defaults with DefaultSettings.
and then