如何全局设置System.Text.Json.JsonSerializer的默认选项?

pkwftd7m  于 2022-12-15  发布在  其他
关注(0)|答案(7)|浏览(236)

而不是这个:

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核心和this one
在.NET Core 3中似乎没有类似的方法来管理JSON序列化默认值,或者我忽略了它?

更新[2020-07-18]:*参见this answer,了解nuget package,其中包含荣誉默认设置的便捷方法。
***更新[2019-12-23]:**部分由于community input的声音,此问题已成为.NET 5.0的added to the roadmap
***更新[2019-10-10]:如果有兴趣看到为System.Text.Json.JsonSerializer*实现的此行为,请前往Chris Yungmann指出的the open GitHub issue*并进行权衡。

ht4b089n

ht4b089n1#

您可以创建扩展方法。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>();
gpfsuwkq

gpfsuwkq2#

不,JsonSerializerOptions不公开默认选项。如果你使用一个特定的web框架,可能有一种方法可以通过它指定(反)序列化设置。否则,我建议创建你自己的方便方法。
另请参见this open issue

uujelgoq

uujelgoq3#

这似乎对我很有效,在启动配置服务:

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

字符串

du7egjpx

du7egjpx4#

默认选项未在.NET Core 3.1的JsonSerializer中公开。但是,截至2019年12月,已将其添加到5.0的路线图中。
.NET 5.0的发布日期为2020年11月expected。但不能保证此特定问题会在任何特定时间得到解决。除了等待,以下答案建议了解决方法:

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

icnyk63a

icnyk63a5#

GitHub用户andre-ss6提出了一个解决方案,如下所示:

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

fiei3ece6#

从.NET7开始,一些字段已经成为自动属性,所以没有办法用@特雷弗Reid在上面的回复中说的来更改它。
新方法是直接更改私有字段:

public static void SetIgnoreNulls() => typeof(JsonSerializerOptions).GetRuntimeFields()
        .Single(f => f.Name == "_defaultIgnoreCondition")
        .SetValue(JsonSerializerOptions.Default, JsonIgnoreCondition.WhenWritingNull);

为什么选择GetRuntimeFields().Single()而不仅仅是GetRuntimeField(%name%)?答案如下:https://github.com/dotnet/runtime/issues/15643

ki0zmccv

ki0zmccv7#

  • (如果您切换到使用Json.NET)*

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

JsonConvert.DefaultSettings = () => MySuperJsonSerializerSettings;

然后

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

相关问题