System.Text.Json 将空字符串全局序列化为空字符串

Kha*_*lil 5 c# .net-core system.text.json

将代码从 newtonsoft json 迁移到 system.text.json 时

我需要所有可为空的字符串呈现为空字符串。

我编写了以下转换器,但所有空字符串值仍呈现为空。

对于空字符串值,不会调用 Write 方法。断点永远不会被击中。

public class EmptyStringConverter : JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => Convert.ToString(reader.GetString(), CultureInfo.CurrentCulture);

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        if (writer == null)
            throw new ArgumentNullException(nameof(writer));
        writer.WriteStringValue(value ?? "");
    }
}
Run Code Online (Sandbox Code Playgroud)

启动代码

services.AddControllers()
    .AddJsonOptions(option =>
    {
        option.JsonSerializerOptions.Converters.Add(new EmptyStringConverter());
    });
Run Code Online (Sandbox Code Playgroud)

控制台示例

class Program
{
    static void Main(string[] args)
    {
        var jsonSerializerOptions = new JsonSerializerOptions();
        jsonSerializerOptions.Converters.Add(new EmptyStringConverter());
        var json = JsonSerializer.Serialize(new Model() { FirstName = null }, jsonSerializerOptions);
    }
}

public class EmptyStringConverter : JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => Convert.ToString(reader.GetString(), CultureInfo.CurrentCulture);

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        if (writer == null)
            throw new ArgumentNullException(nameof(writer));
        writer.WriteStringValue(value ?? "");
    }
}

public class Model
{
    public string FirstName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

dbc*_*dbc 12

在 .NET 5.0 中JsonConverter<T>.HandleNull,这可以通过覆盖并返回来完成true:

public class EmptyStringConverter : JsonConverter<string>
{
    public override bool HandleNull => true;
    
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => reader.TokenType == JsonTokenType.Null ? "" : reader.GetString();

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) =>
        writer.WriteStringValue(value ?? "");
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅处理空值。

演示小提琴在这里。

在 .NET Core 3.x 中,这未实现。来自处理.NET Core 3.x 中的空值:

处理空值

默认情况下,序列化程序按如下方式处理空值:

  • 对于参考类型和Nullable<T>类型:

    • 它不会在序列化时将 null 传递给自定义转换器。
    • 它不会在反序列化时将 JsonTokenType.Null 传递给自定义转换器。
    • 它在反序列化时返回一个空实例。
    • 它在序列化时直接使用 writer 写入 null。
  • 对于不可为 null 的值类型:

    • 它将 JsonTokenType.Null 传递给反序列化时的自定义转换器。(如果没有可用的自定义转换器,则该类型的内部转换器将引发 JsonException 异常。)

这种空处理行为主要是为了通过跳过对转换器的额外调用来优化性能。此外,它还避免了强制可为 null 类型的转换器在每个 Read 和 Write 方法重写开始时检查 null。