Home > Enterprise >  IgnoreNullValue not working when serializing an Anonymous Object
IgnoreNullValue not working when serializing an Anonymous Object

Time:04-26

The Problem

I am creating an anonymous object in a method and assigning it properties from a class. Some of the properties can sometimes be empty (strings) and I eventually need to serialize the anonymous object to a JSON string.

When it gets serialized as JSON, I want to get rid of nulls or empty strings. I actually want to do this on a property by property basis (not generically ignoring all nulls) but it doesn't seem to be working at all!

The Code

public class Refrigerator {
    public string Brand { get; set; }
    public bool HasFood { get; set; }



    public void Serialize() {

        //ANONYMOUS OBJECT HERE
        var fridge = new {
           Brand = this.Brand; //THIS VALUE IS SOMETIMES AN EMPTY STRING!!
           HasFood = this.HasFood;
        }
        
        var value = Newtonsoft.Json.JsonConvert.SerializeObject(fridge);

        //value contains Brand as an empty string
    }

}

What I've Tried

        var fridge = new {
           Brand = this.Brand;
           HasFood = this.HasFood;

           //JsonSerializer should check this function I thought?
           ShouldSerializeBrand = new Func<bool>() {
               if(String.IsNullOrEmpty(this.Brand){
                 return false;
               }
               return true;
           }
        }

        //This should also work, but doesn't.......
        var value = Newtonsoft.Json.JsonConvert.SerializeObject(fridge, new JsonSerializerSettings 
        {
          NullValueHandling = NullValueHandling.Ignore,
          DefaultValueHandling = DefaultValueHandling.Ignore
        });

        //JSON STILL contains Brand as an empty string!!! Its still there!

Any ideas why its not working?

CodePudding user response:

One of the way for this could be that, you can use ExpandoObject for this like :

dynamic fridge = new ExpandoObject();
 if(!String.IsNullOrEmpty(this.Brand))
 {
     fridge.Brand = this.Brand;
 }
 fridge.HasFood = this.HasFood; 

This way the anonymous object will not have Brand property created unless it has a value. Now if the Brand is null of empty string, the property won't be created on the anonymous object we have created.

See this DEMO FIDDLE as example.

CodePudding user response:

An empty string i.e. the literal "" is neither a null value nor the default for a string type. As such, both options from your JsonSerializerSettings will fail to do what you want. You can solve the problem by doing what you already tried, or by creating a custom JSONConverter to add in your specific serialization logic.

Sample code based off the Newtonsoft samples:

public class FridgeJsonConverter : JsonConverter
{
 private readonly Type[] _types;

 public FridgeJsonConverter(params Type[] types)
 {
    _types = types;
 }

 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
 {
    JToken t = JToken.FromObject(value);

    if (t.Type != JTokenType.Object)
    {
        t.WriteTo(writer);
    }
    else
    {
        JObject o = (JObject)t;
        var brandProp = o.Properties().First(x => x.Name == "Brand");
        if(brandProp.Value.ToString() == string.Empty)
         o.Remove(brandProp.Name);

        o.WriteTo(writer);
    }
 }

 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 {
    throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
 }

 public override bool CanRead
 {
    get { return false; }
 }

 public override bool CanConvert(Type objectType)
 {
    return _types.Any(t => t == objectType);
 }
}

Then, in your calling code, do this:

string json = JsonConvert.SerializeObject(fridge, Formatting.Indented, new FridgeJsonConverter(typeof(Fridge)));
  • Related