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

k75qkfdt  于 2023-01-14  发布在  其他
关注(0)|答案(2)|浏览(190)

我想从我的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);
    }
}

我有一个JsonSerializerClass,它基本上是System.Text.Json.JsonSerializer的 Package 器,这个类使用了Converter:

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;
    }
}

下面是我的测试案例:

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());

我本以为MiddleName不在json中,因为空字符串会变成null,并且null值应该从json中删除,但是MiddleName却在json中,值为null

xytpbqjk

xytpbqjk1#

在.NET 7中,您可以使用Modifier来影响序列化过程(announcement blog中提供了更多信息):

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);
        }
    }
}

在本例中,所有内容都与ShouldSerialize属性有关,该属性接受value,并允许您决定是否应该序列化它。
使用上面链接的属性添加修饰符:

var jsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers = { ExcludeEmptyStrings }
    }
};

.NET Fiddle

0tdrvxhp

0tdrvxhp2#

你可以试试这个自定义转换器

var options = new System.Text.Json.JsonSerializerOptions { WriteIndented = true };
    options.Converters.Add(new IgnoreNullOrEmptyStringJsonConverter<Person>());
    var json = System.Text.Json.JsonSerializer.Serialize(person, options);

public class IgnoreNullOrEmptyStringJsonConverter<T> : System.Text.Json.Serialization.JsonConverter<T> where T : class
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // Use default implementation when deserializing (reading)
        return System.Text.Json.JsonSerializer.Deserialize<T>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        using (JsonDocument document = System.Text.Json.JsonSerializer.SerializeToDocument(value))
        {
            foreach (var property in document.RootElement.EnumerateObject())
            {
                if (property.Value.ValueKind.ToString() != "Null" 
                   && !(property.Value.ValueKind.ToString() == "String" 
                   && string.IsNullOrEmpty(property.Value.ToString())))
                    property.WriteTo(writer);
            }
        }
        writer.WriteEndObject();
    }
}

输出

{
  "Name": "John",
  "LastName": "Doe"
}

也可以使用此函数

var json = GetIgnoreNullOrEmptyStringJson(person);

public string GetIgnoreNullOrEmptyStringJson<T>(T value) where T : class
{
    var jNode = System.Text.Json.JsonSerializer.SerializeToNode(value);

    var props = jNode.AsObject()
        .Where(prop => (prop.Value == null
               || (prop.Value.GetValue<JsonElement>().ValueKind.ToString() == "String"
               && string.IsNullOrEmpty(prop.Value.ToString()))))
        .Select(e => e)
        .ToArray();

    for (var i = 0; i < props.Length; i++)
        jNode.AsObject().Remove(props[i].Key);

    return System.Text.Json.JsonSerializer.Serialize(jNode, new System.Text.Json.JsonSerializerOptions { WriteIndented = true });
}

相关问题