1

Closed

NullValueHandling with ExpandoObject

description

Hi, I encountered a bug with ExpandoObject. It seems that the setting NullValueHandling (Ignore) will be not applied if it is an ExpandoObject.
Please have a look at it.
 
[Test]
public void ExpandoObjectNullHandling()
{
// arrange
dynamic dyn = new ExpandoObject();
 
dyn.id = "test";
dyn.val = (string)null;
 
// act
var json = JsonConvert.SerializeObject(
    dyn, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
 
// assert
StringAssert.DoesNotContain("null", json);
}
Closed Jul 29, 2012 at 3:35 AM by JamesNK
NullValueHandling is for properties, not untyped classes like dynamic or dictionaries.

comments

SeriousM wrote Jul 10, 2012 at 1:15 PM

This implementation does the job for me, maybe you can use it?
public static object RemoveExpandoObjectNullValues(object objectToCheck)
{
    // a workaround for the nullvaluehandling bug in json.net http://json.codeplex.com/workitem/23008

    if (objectToCheck == null || objectToCheck.GetType().BaseType == typeof(ValueType) || objectToCheck.GetType().BaseType == typeof(Enum) || objectToCheck is string)
    {
        return objectToCheck;
    }

    var listObject = objectToCheck as IEnumerable<object>;

    if (listObject != null)
    {
        var newList = new List<object>();

        foreach (var listItem in listObject)
        {
            newList.Add(RemoveExpandoObjectNullValues(listItem));
        }

        return newList;
    }

    var expandoObject = objectToCheck as IDictionary<string, object>;

    if (expandoObject == null)
    {
        return objectToCheck;
    }

    var keys = expandoObject.Keys.ToList();

    for (int i = keys.Count - 1; i >= 0; i--)
    {
        var item = RemoveExpandoObjectNullValues(expandoObject[keys[i]]);

        if (item == null)
        {
            expandoObject.Remove(keys[i]);
            continue;
        }

        var otc = item as IDictionary<string, object>;

        if (otc != null && otc.Keys.Count == 0)
        {
            expandoObject.Remove(keys[i]);
        }
    }

    return objectToCheck;
}