Remove empty string properties from json serialized object
i have done this with a converter.
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace TestApp.JsonConverterResolver
{
public class IgnoreEmptyStringsConverter : JsonConverter
{
#region Methods
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var theValue = reader.Value?.ToString();
return !string.IsNullOrWhiteSpace(theValue) ? theValue : null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (!string.IsNullOrWhiteSpace(value.ToString()))
{
JToken token = JToken.FromObject(value.ToString(), serializer);
token.WriteTo(writer);
return;
}
writer.WriteNull();
}
#endregion
}
}
Example person model class:
public class Person
{
public string Name { get; set; }
}
And the ueage:
var serializerSettings = new JsonSerializerSettings
{
Formatting = Newtonsoft.Json.Formatting.Indented,
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
Converters = new List<JsonConverter> {new IgnoreEmptyStringsConverter()}
};
var person = JsonConvert.DeserializeObject<Person>("{ \"Name\":\"\" }", serializerSettings);
var jsonPerson = JsonConvert.SerializeObject(new Person { Name = "" }, serializerSettings);
I just wrote that out of my head. But I think that's how I solved it at some point. Maybe it helps someone.
Although the accepted answers works, it also removes integer properties of zero value. I was looking for something more generic to work with large objects.
Found a great answer here: https://codearticles.ru/articles/2905?AspxAutoDetectCookieSupport=1
And consolidated it for our use case as below:
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.PropertyType == typeof(string))
{
// Do not include emptry strings
property.ShouldSerialize = instance =>
{
return !string.IsNullOrWhiteSpace(instance.GetType().GetProperty(member.Name).GetValue(instance, null) as string);
};
}
else if (property.PropertyType == typeof(DateTime))
{
// Do not include zero DateTime
property.ShouldSerialize = instance =>
{
return Convert.ToDateTime(instance.GetType().GetProperty(member.Name).GetValue(instance, null)) != default(DateTime);
};
}
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
// Do not include zero-length lists
switch (member.MemberType)
{
case MemberTypes.Property:
property.ShouldSerialize = instance =>
{
var enumerable = instance.GetType().GetProperty(member.Name).GetValue(instance, null) as IEnumerable;
return enumerable != null ? enumerable.GetEnumerator().MoveNext() : false;
};
break;
case MemberTypes.Field:
property.ShouldSerialize = instance =>
{
var enumerable = instance.GetType().GetField(member.Name).GetValue(instance) as IEnumerable;
return enumerable != null ? enumerable.GetEnumerator().MoveNext() : false;
};
break;
}
}
return property;
}
}
This can be used as follows:
JsonConvert.SerializeObject(o,
Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = ShouldSerializeContractResolver.Instance
});
Just decorating the properties [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
ONLY should do what you want. Unless the property is getting set to an empty string.
Just wondering, why do you need the DataMemeber attribute?
Here is a link to a working dotnetfiddle
using System;
using Newtonsoft.Json;
using System.ComponentModel;
public class Program
{
public static void Main()
{
var user = new User();
user.UserID = "1234";
user.ssn = "";
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.DefaultValueHandling = DefaultValueHandling.Ignore;
Console.WriteLine(JsonConvert.SerializeObject(user, settings));
}
}
public class User
{
[DefaultValue("")]
public string UserID { get; set; }
[DefaultValue("")]
public string ssn { get; set; }
[DefaultValue("")]
public string empID { get; set; }
[DefaultValue("")]
public string schemaAgencyName { get; set; }
[DefaultValue("")]
public string givenName { get; set; }
[DefaultValue("")]
public string familyName { get; set; }
[DefaultValue("")]
public string password { get; set; }
}
You can also use two annotations as follows:
[DefaultValue("")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Category { get; set; }