Reputation: 4500
I'm using Newtonsoft's Json.NET 7.0.0.0 to serialize classes to JSON from C#:
class Foo
{
public string X;
public List<string> Y = new List<string>();
}
var json =
JsonConvert.SerializeObject(
new Foo(),
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
The value of json
here is
{ "Y": [] }
but I would like it to be { }
if Y
is an empty list.
I couldn't find a satisfactory way to achieve this. Maybe with a custom contract resolver?
Upvotes: 15
Views: 7420
Reputation: 10879
If you're looking for a solution which can be used generically across different types and does not require any modification (attributes, etc), then the best solution that I can think if would be a custom DefaultContractResolver
class. It would use reflection to determine if any IEnumerable
s for a given type are empty.
public class IgnoreEmptyEnumerablesResolver : DefaultContractResolver
{
public static readonly IgnoreEmptyEnumerablesResolver Instance = new IgnoreEmptyEnumerablesResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType != typeof(string) &&
typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
property.ShouldSerialize = instance =>
{
IEnumerable enumerable = null;
// this value could be in a public field or public property
switch (member.MemberType)
{
case MemberTypes.Property:
enumerable = instance
.GetType()
.GetProperty(member.Name)
.GetValue(instance, null) as IEnumerable;
break;
case MemberTypes.Field:
enumerable = instance
.GetType()
.GetField(member.Name)
.GetValue(instance) as IEnumerable;
break;
default:
break;
}
if (enumerable != null)
{
// check to see if there is at least one item in the Enumerable
return enumerable.GetEnumerator().MoveNext();
}
else
{
// if the list is null, we defer the decision to NullValueHandling
return true;
}
};
}
return property;
}
}
Upvotes: 14
Reputation: 379
If you can modify your classes, you could add Shrink method and set null for all empty collections. It requires to change the class but it has better performance. Just another option for you.
Upvotes: 0