如何使用 System.Text.Json.JsonSerializer 从 json 中删除空字符串属性?

Mar*_*ijn 3 c# json .net-core asp.net-core

我想从 Json 中省略空字符串属性。

这就是我所做的。

创建一个将空字符串转换为 null 的自定义转换器:

public class EmptyStringToNullConverter : JsonConverter<string>
{
    public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return reader.GetString();
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        if (value == string.Empty)
            writer.WriteNullValue();
        else
            writer.WriteStringValue(value);
    }
}
    
Run Code Online (Sandbox Code Playgroud)

我有一个JsonSerializerClass,它基本上是一个包装器System.Text.Json.JsonSerializer,这个类正在使用转换器:

    public class JsonSerializerClass
{
    private JsonSerializerOptions serializeOptions;
    private JsonSerializerOptions deserializeOptions;

    public JsonSerializerClass()
    {
        serializeOptions = new JsonSerializerOptions();
        deserializeOptions = new JsonSerializerOptions();
        InitSerializer();
        InitDeserializer();
    }

    public JsonSerializerOptions SerializeOptions => serializeOptions;

    public string Serialize(object value)
    {
        return Serialize(value, serializeOptions);
    }

    public T Deserialize<T>(string json)
    {
        var o = System.Text.Json.JsonSerializer.Deserialize<T>(json, deserializeOptions);

        if (o == null)
            throw new ArgumentException($"Cannot deserialize JSON to type {typeof(T)}: {json}");

        return o;
    }

    public static string Serialize(object value, JsonSerializerOptions options)
    {
        return System.Text.Json.JsonSerializer.Serialize(value, options);
    }

    private void InitSerializer()
    {
        serializeOptions.Converters.Add(new EmptyStringToNullConverter());

        serializeOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    }

    private void InitDeserializer()
    {
        deserializeOptions.PropertyNameCaseInsensitive = true;

        deserializeOptions.Converters.Add(new JsonStringEnumConverter());
        deserializeOptions.Converters.Add(new DateOnlyConverter());
        deserializeOptions.Converters.Add(new DateOnlyNullableConverter());
        deserializeOptions.Converters.Add(new IntConverter());
        deserializeOptions.Converters.Add(new DecimalConverter());

        deserializeOptions.IncludeFields = true;
        deserializeOptions.AllowTrailingCommas = true;
        deserializeOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString;
        deserializeOptions.ReadCommentHandling = JsonCommentHandling.Skip;
    }
}    
Run Code Online (Sandbox Code Playgroud)

这是我的测试用例:

var person = new Person
{
    Name = "John",
    LastName = "Doe",
    MiddleName = ""
};
var serializer = new JsonSerializerClass();

var json = serializer.Serialize(person);

json.ToLower().Should().NotContain(nameof(person.MiddleName).ToLower());
Run Code Online (Sandbox Code Playgroud)

我希望它MiddleName不在 json 中,因为空字符串会变为 null,并且应从 json 中删除 null 值。而是MiddleName在 json 中,带有 value null

Kir*_*kin 5

在 .NET 7 中,您可以使用修饰符来影响序列化过程(更多信息请参阅公告博客):

static void ExcludeEmptyStrings(JsonTypeInfo jsonTypeInfo)
{
    if (jsonTypeInfo.Kind != JsonTypeInfoKind.Object)
        return;

    foreach (JsonPropertyInfo jsonPropertyInfo in jsonTypeInfo.Properties)
    {
        if (jsonPropertyInfo.PropertyType == typeof(string))
        {
            jsonPropertyInfo.ShouldSerialize = static (obj, value) => 
                !string.IsNullOrEmpty((string)value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,一切都与ShouldSerialize属性有关,该属性接受value并允许您决定是否应将其序列化。

使用我上面链接的属性添加修饰符:

var jsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers = { ExcludeEmptyStrings }
    }
};
Run Code Online (Sandbox Code Playgroud)

.NET 小提琴