Reputation: 2912
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