【问题标题】:How to globally set default options for System.Text.Json.JsonSerializer?如何为 System.Text.Json.JsonSerializer 全局设置默认选项?
【发布时间】:2020-02-08 09:42:31
【问题描述】:

而不是这个:

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 的实例,并为异常而不是规则覆盖。

this q & a 所示,这是 Json.Net 的一个有用功能。我在the documentation 中查看了System.Text.Json 以及this GitHub repo 中的.NET Core。还有this one

在 .NET Core 3 中似乎没有管理 JSON 序列化默认值的类比。还是我忽略了它?


【问题讨论】:

  • There doesn't seem to be an analog for managing JSON serialization defaults in Core-3 -- 您是在谈论进出 API 的请求吗?还是对其他资源的请求和响应?
  • @ps2goat 我不确定我是否理解您的问题。这里的问题是(反)序列化 JSON 字符串。它们可以来自任意数量的来源。
  • 我之所以问,是因为在启动过程中有一些特殊的地方用于输入和输出格式化程序(例如,用于模型绑定)
  • 啊,明白了。从这个意义上说,我认为我们的案例将属于“其他资源”。 @ps2goat

标签: c# json serialization .net-core system.text.json


【解决方案1】:

您可以创建扩展方法。 Here's an example

我使用单独的方法而不是必须构建特殊设置,以便所有设置都在一个位置并且易于重复使用。

public static class DeserializeExtensions
{
    private static JsonSerializerOptions defaultSerializerSettings = new JsonSerializerOptions();

    // set this up how you need to!
    private static JsonSerializerOptions featureXSerializerSettings = new JsonSerializerOptions();


    public static T Deserialize<T>(this string json)
    {       
        return JsonSerializer.Deserialize<T>(json, defaultSerializerSettings);
    }

    public static T DeserializeCustom<T>(this string json, JsonSerializerOptions settings)
    {
        return JsonSerializer.Deserialize<T>(json, settings);
    }

    public static T DeserializeFeatureX<T>(this string json)
    {
        return JsonSerializer.Deserialize<T>(json, featureXSerializerSettings);
    }
}

然后您将其作为字符串的方法调用,无论是文字还是变量。

    Car result = @"{""Wheels"": 4, ""Doors"": 2}".DeserializeFeatureX<Car>();

【讨论】:

    【解决方案2】:

    不,JsonSerializerOptions 不会公开default options。如果您使用的是特定的 Web 框架,则可能有一种方法可以通过它指定(反)序列化设置。否则,我建议您创建自己的便捷方法。

    另见this open issue

    【讨论】:

      【解决方案3】:

      默认选项未在 .NET Core 3.1 的 JsonSerializer 中公开。但是,截至 2019 年 12 月,对于 5.0,这一直是 added to the road map

      .NET 5.0 的发布日期为 expected2020 年 11 月。但不能保证此特定问题会在任何特定时间得到解决。除了等待之外,这些答案还提供了一些解决方法:

      此外,受@ps2goat 的回答启发,我打包了我的便利扩展方法,并将它们放在nuget.orggithub 上:

      【讨论】:

        【解决方案4】:

        这似乎对我有用,在 StartUp.ConfigureServices 中:

        services.AddControllers().AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
                options.JsonSerializerOptions.PropertyNamingPolicy=JsonNamingPolicy.CamelCase;
            });
        

        【讨论】:

        • 它确实有效。但是,它特定于配置控制器。
        • @TrevorReid 好点,如果你例如,这是一个问题。使用 Refit 从您的 asp.net 核心进行 API 调用 --> 然后 Refit 将忽略这些设置。
        【解决方案5】:

        GitHub用户andre-ss6提出了一个workaround,如下:

        ((JsonSerializerOptions)typeof(JsonSerializerOptions)
            .GetField("s_defaultOptions", 
                System.Reflection.BindingFlags.Static |
                System.Reflection.BindingFlags.NonPublic).GetValue(null))
            .PropertyNameCaseInsensitive = true;
        

        【讨论】:

        • 这很好用,但很脆弱。我将使用它(我正在注册自定义类型转换器,不更改 PropertyNameCaseInsensitive,但前提是相同的)并祈祷它一直有效,直到 2020 年 11 月的预期发布,官方支持设置默认选项。
        • 工作正常!谢谢
        【解决方案6】:

        (如果你曾经改用 Json.NET)

        我更喜欢并建议使用明确的设置并将设置传递给所有调用,但您可以使用 DefaultSettings 设置默认值。

        JsonConvert.DefaultSettings = () => MySuperJsonSerializerSettings;
        

        然后

        var json = JsonConvert.SerializeObject(o1);
        var o2 = JsonConvert.DeserializeObject(x);
        

        【讨论】:

        • 我猜你被否决了,因为问题是指 System.Text.Json 而不是 Newtonsofts (更好)包。在我的情况下,我没有选择“切换”到 Json.Net,因为在这个 Blazor Web 组装项目中该选项已被我拿走了。它远非伟大,它就是这样
        • “好多了”是一个观点问题——Newtonsoft.JSON 在配置和支持怪异(甚至无效的 json)方面肯定是“更好”的。但是,System.Text.Json 在性能(内存和 CPU)方面更好。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-16
        • 1970-01-01
        • 2023-04-11
        • 1970-01-01
        相关资源
        最近更新 更多