Kjara
Kjara

Reputation: 2912

do not serialize empty collections (and handle accordingly in deserialization)

I have a bunch of POCOs that can be (de-)serialized from/to json. A lot of content is collections. I want the serialized JSON to only contain a specific property if its collection is not empty (reasons: saving space, making it much easier for humans to see what's relevant). Deserialization of those non-existing properties should result in empty collections in the data.

How do I do that?


JsonIgnoreCondition does not have any entry that does this. It only handles null/default values.


Example POCO:

public class Data
{
    public DocData MainDoc { get; }
    public IList<DocData> SubDocs { get; }

    public Data(DocData mainDoc, IList<DocData> subDocs)
    {
        MainDoc = mainDoc;
        SubDocs = subDocs;
    }
}

I do the (de-)serialization with JsonSerializer.Serialize and JsonSerializer.Deserialize<Data> with JsonSerializerOptions argument new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }.

Actual JSON if there is no content inside SubDocs:

{
    "MainDoc": { ... },
    "SubDocs": [ ]
}

Wanted JSON if there is no content inside SubDocs:

{
    "MainDoc": { ... }
}

I already tried writing an own converter returning null if the collection is empty:

public class Data
{
    public DocData MainDoc { get; }
    [JsonConverter(typeof(CollectionConverter))]
    public IList<DocData> SubDocs { get; }
}

internal class CollectionConverter : JsonConverter<IList<DocData>>
{
    public override IList<DocData>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var deserialized = (IList<DocData>?)JsonSerializer.Deserialize(ref reader, typeToConvert, options);
        return deserialized ?? List<DocData>.Empty;
    }

    public override void Write(Utf8JsonWriter writer, IList<DocData> values, JsonSerializerOptions options)
    {
        if (!values.Any())
        {
            writer.WriteNullValue();
            return;
        }

        writer.WriteStartArray();
        foreach (var value in values)
            JsonSerializer.Serialize(writer, value, options);
        writer.WriteEndArray();
    }
}

, hoping that JsonIgnoreCondition.WhenWritingNull or JsonIgnoreCondition.WhenWritingDefault would combine well with that. But no, I just get this JSON then:

{
    "MainDoc": { ... },
    "SubDocs": null
}

Upvotes: 1

Views: 117

Answers (0)

Related Questions