Phi*_*l K 15 c# json asp.net-core system.text.json
System.Text.Json
我通过切换到ASP.NET Core 应用程序,意外地在 API 中引入了重大更改。我有一个客户端正在发送 JSON 文档,并使用数字1
or0
作为布尔字段而不是true
or 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在这里。
笔记:
Json.NET 自动尝试反序列化字符串,以bool
使用有序且不区分大小写bool.TryParse()
的比较进行解析。 简单地检查eg不会模拟Newtonsoft 的大小写不变性。Utf8JsonReader.ValueTextEquals("true")
Json.NET 支持反序列化整数和浮点数,方法bool
是尝试将值标记解析为long
or double
(或decimal
何时FloatParseHandling.Decimal
设置),然后调用Convert.ToBoolean()
结果。转换器模拟此逻辑。
可能存在一些边界条件,其中 myBoolConverter<bool>
和 Json.NET 的行为不相同,特别是在溢出或舍入接近零的情况下。
如果您还需要支持将数字反序列化为bool?
,请NullableConverterFactory
从这个答案中获取How to deserialize an empty string to a null value for all `Nullable<T>` value types using System.Text.Json? 并将其添加到转换器中,如下所示:
var options = new JsonSerializerOptions
{
Converters = { new BoolConverter(), new NullableConverterFactory() },
};
Run Code Online (Sandbox Code Playgroud)
此转换器工厂还修复了从 Newtonsoft 到 System.Text.Json 的另一个不起眼的重大更改,即前者会将空 JSON 字符串反序列化为""
任何字符串,Nullable<T>
但后者不会。
演示小提琴#2在这里。
归档时间: |
|
查看次数: |
5845 次 |
最近记录: |