tags:

views:

1362

answers:

4

I want to remove all null properties in a generic object. It doesn't have to be recursive, one level deep is also fine.

The reason I need is for a custom JavascriptConvertor implementation for JSON serialization which gives me: {"Name":"Aleem", "Age":null, "Type":"Employee"}

And I would like to skip over the null object.

The function for this task takes in the objct and returns a Dictionary:

IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)

So I would like to remove all null properties from obj. All properties have getter but if the property is not set, the getter returns null.

A: 

You may want to create some sort of wrapping object that only exposes members of what it is wrapping if they are not null.

You may also want to check out version 4 of C#. From the wikipedia entry for duck typing:

Version 4 release of C# have extra type annotations that instruct the compiler to arrange for type checking of classes to occur at run-time rather than compile time, and include run-time type checking code in the compiled output. Such additions allow the language to enjoy most of the benefits of duck typing with the only drawback being the need to identify and specify such dynamic classes at compile time.

Klathzazt
+4  A: 

You can implement your own JavaScriptConverter to handle serialization of your type. Then you get full control on how properties are serialized.

@Richards answer provides a nice implementation of the Serialize method.

The Deserialize method would be quite similar but I'll leave the implementation up to you. Now the only drawback with JavaScriptConverter is that it has to get the supported types from somewhere. Either hardcode it like this:

public override IEnumerable<Type> SupportedTypes
{ 
    get
    {
        var list = new List<Type>{ typeof(Foo), typeof(Bar)...};
        return list.AsReadOnly();
    }
}

...or make it configurable, e.g. via the class constructor.

Peter Lillevold
Peter, this is for a custom JavascriptConvertor
aleemb
Exactly. If the standard converter includes properties that are null you could create your own converter that ignores these properties and register it with the serializer.
Peter Lillevold
He's right though, but you need to cast the object to your type Serialize(object obj,... MyObject o = (MyObject)obj; then check if property is not null add to dictionary for serialization ...
Chad Grant
The object can be of any type: Foo, Bar, etc. And it can have any number of properties... I'd like to have a generic solution than handle each object type individually.
aleemb
*than = rather than
aleemb
+1  A: 

Something along the lines of the following will probably do the trick:

public IDictionary<string, object> GetNonNullProertyValues(object obj)
{
    var dictionary = new Dictionary<string, object>();

    foreach (var property in obj.GetType().GetProperties())
    {
        var propertyValue = property.GetValue(obj, null);
        if (propertyValue != null)
        {
            dictionary.Add(property.Name, propertyValue);
        }
    }

    return dictionary;
}

NB: this method does not handle indexed properties.

Richard
+1  A: 
 using System.IO;
 using System.Runtime.Serialization.Json;

    public static class JsonExtensions
    {
        public static string ToJson<T>(this T instance) 
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream memoryStream = new MemoryStream())
            {
                serializer.WriteObject(memoryStream, instance);

                memoryStream.Flush();
                memoryStream.Position = 0;

                using (var reader = new StreamReader(memoryStream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        public static T FromJson<T>(this string serialized) 
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (StreamWriter writer = new StreamWriter(memoryStream))
                {
                    writer.Write(serialized);
                    writer.Flush();

                    memoryStream.Position = 0;

                    return (T)serializer.ReadObject(memoryStream);
                }
            }
        }
    }
Chad Grant
What do you have to reference to get System.Runtime.Serialization.Json?
Svish
System.ServiceModel.Web and System.Runtime.Serialization
Chad Grant