自动将数字转换为布尔值 - 从 Newtonsoft 迁移到 System.Text.Json

Phi*_*l K 15 c# json asp.net-core system.text.json

System.Text.Json我通过切换到ASP.NET Core 应用程序,意外地在 API 中引入了重大更改。我有一个客户端正在发送 JSON 文档,并使用数字1or0作为布尔字段而不是trueor false

// What they're sending.
{ "Active": 1 }

// What they should be sending.
{ "Active": true }
Run Code Online (Sandbox Code Playgroud)

Newtonsoft.Json通过将数字转换为布尔值(0 = false,其他 = true)来自动处理此问题,但System.Text.Json不会这样做;它会抛出异常。1这意味着我的 API 端点突然停止为发送's 和0's的愚蠢客户工作!

我似乎在迁移指南中找不到任何提及这一点。我想将行为恢复到 Newtonsoft 处理它的方式,但我不确定是否有一个标志可以在我看不到的地方启用它,或者我是否必须编写一个自定义转换器。

有人可以帮我恢复像 Newtonsoft 一样的行为吗?


下面是一些代码来演示该问题:

using System;

string data = "{ \"Active\": 1 }";

try
{
    OutputState s1 = System.Text.Json.JsonSerializer.Deserialize<OutputState>(data);
    Console.WriteLine($"OutputState 1: {s1.Active}");
}
catch (Exception ex)
{
    Console.WriteLine($"System.Text.Json failed: {ex.Message}");
}

try
{
    OutputState s2 = Newtonsoft.Json.JsonConvert.DeserializeObject<OutputState>(data);
    Console.WriteLine($"OutputState 2: {s2.Active}");
}
catch (Exception ex)
{
    Console.WriteLine($"Newtonsoft.Json failed: {ex.Message}");
}

public record OutputState(bool Active);
Run Code Online (Sandbox Code Playgroud)

还有一个用于交互式游乐场的 .NET 小提琴:https ://dotnetfiddle.net/xgm2u7

dbc*_*dbc 27

您可以创建一个JsonConverter<bool>模拟 Json.NET 逻辑的自定义JsonReader.ReadAsBoolean()

public class BoolConverter : JsonConverter<bool>
{
    public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) =>
        writer.WriteBooleanValue(value);
    
    public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
        reader.TokenType switch
        {
            JsonTokenType.True => true,
            JsonTokenType.False => false,
            JsonTokenType.String => bool.TryParse(reader.GetString(), out var b) ? b : throw new JsonException(),
            JsonTokenType.Number => reader.TryGetInt64(out long l) ? Convert.ToBoolean(l) : reader.TryGetDouble(out double d) ? Convert.ToBoolean(d) : false,
            _ => throw new JsonException(),
        };
}
Run Code Online (Sandbox Code Playgroud)

通过将其添加到以下位置来使用JsonSerializerOptions.Converters

var options = new JsonSerializerOptions
{
    Converters = { new BoolConverter() },
};
var s1 = System.Text.Json.JsonSerializer.Deserialize<OutputState>(data, options);
Run Code Online (Sandbox Code Playgroud)

演示小提琴#1在这里

笔记:

  • 或者,您可以使用属性指定转换器来反序列化特定属性:`[JsonConverter(typeof(BoolConverter))]bool Active { get;set; }`。然后你只需像往常一样调用“反序列化”即可。 (4认同)