Reputation: 116958
I am trying to figure out how to serialize to a json object and skip serializing properties whose values are empty lists. I am not using Newtonsoft json
using System.Text.Json;
using System.Text.Json.Serialization;
using AutoMapper;
I have an object with a property.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("extension")]
public List<Extension> Extension { get; set; }
When I try to serialize this object using the following
var optionsJson = new JsonSerializerOptions
{
WriteIndented = true,
IgnoreNullValues = true,
PropertyNameCaseInsensitive = true,
};
var json = JsonSerializer.Serialize(report, optionsJson);
It still gives me an empty array:
"extension": [],
Isn't there a way to keep it from serializing these empty lists? I would like to see extension
gone. It should not be there at all. I need to do this because the gateway will respond with an error if I send:
"extension": null,
It must not be part of the object when serialized.
The reason why I do not want these empty lists is that the third party gateway I am sending to objects to empty lists
"severity": "error", "code": "processing", "diagnostics": "Array cannot be empty - the property should not be present if it has no values", "location": [ "Bundle.entry[2].resource.extension", "Line 96, Col 23" ]
I'm trying to avoid doing some kind of nasty string replace on this.
Upvotes: 11
Views: 11203
Reputation: 1684
A cleaner and reusable approach without adjustments to the DTO class.
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
namespace StackOverflowQuestionsAndAnswers
{
public class SomeClassWithEmptyList
{
// Your property that is expected in the json output
public string Name { get; set; } = "Some Name";
// Your empty list which is not expected in the json output
public List<string> List { get; set; } = new List<string>();
}
public static class JsonEmptyListTestCase
{
public static void Run()
{
string json = JsonSerializer.Serialize(new SomeClassWithEmptyList(), GetOptions());
Console.WriteLine(json);
JsonSerializerOptions GetOptions() => new JsonSerializerOptions()
{
WriteIndented = true,
Converters = { new JsonStringEnumConverter() },
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
// This modifier will suppress empty lists
Modifiers = { IgnoreEpmptyListOfStrings }
}
};
}
private static void IgnoreEpmptyListOfStrings(JsonTypeInfo typeInfo)
{
if (typeInfo.Type != typeof(SomeClassWithEmptyList))
return;
var listOfStringProperties = typeInfo.Properties.Where(p => p.PropertyType == typeof(List<string>));
foreach (JsonPropertyInfo propertyInfo in listOfStringProperties)
propertyInfo.ShouldSerialize = ShouldSerializeListOfString;
static bool ShouldSerializeListOfString(object _, object? value) => ListOfStringNotNullOrEmpty(value as List<string>);
static bool ListOfStringNotNullOrEmpty(List<string>? list) => list != null && list.Any();
}
}
}
Resulting Json :
{
"Name": "Some Name"
}
Upvotes: 3
Reputation: 391336
You can add a dummy property that is used during serialization that handles this.
JsonPropertyNameAttribute
to ensure it is being serialized with the correct name, and also with the JsonIgnoreAttribute
so that it will not be serialized when it returns null.null
(and thus be ignored) when the actual property contains an empty list, otherwise it would return that (non-empty) listSomething like this:
[JsonIgnore]
public List<Extension> Extensions { get; set; } = new();
[JsonPropertyName("extension")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<Extension> SerializationExtensions
{
get => Extensions?.Count > 0 ? Extensions : null;
set => Extensions = value ?? new();
}
Upvotes: 14