Remove null properties of an object sent to Json MVC

asp.net-mvc-5, c#, json, serialization

Solution

You can't use the default `Json ActionResult` to remove null properties.

You can take a look at JSON.NET, it has an attribute that you can set to remove the property if it is null

[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]

Or if you don't want to use other libraries you can create your own json custom ActionResult and register a new converter for the default `JavaScriptSerializer`, like this:

public class JsonWithoutNullPropertiesResult : ActionResult
{
    private object Data { get; set; }

    public JsonWithoutNullPropertiesResult(object data)
    {
        Data = data;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        HttpResponseBase response = context.HttpContext.Response;
        response.ContentType = "application/x-javascript";
        response.ContentEncoding = Encoding.UTF8;

        if (Data != null)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new[] { new NullPropertiesConverter() });
            string ser = serializer.Serialize(Data);
            response.Write(ser);
        }
    }
}

public class NullPropertiesConverter : JavaScriptConverter
{
    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var toSerialize = new Dictionary<string, object>();

        foreach (var prop in obj.GetType()
                                .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                .Select(p => new
                                {
                                    Name = p.Name,
                                    Value = p.GetValue(obj)
                                })
                                .Where(p => p.Value != null))
        {
            toSerialize.Add(prop.Name, prop.Value);
        }

        return toSerialize;
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get { return GetType().Assembly.GetTypes(); }
    }
}

And now in your view:

public ActionResult Index()
{
    Teetimes r = BookingManager.GetBookings();
    return new JsonWithoutNullPropertiesResult(t);
}

Problem

``` namespace Booking.Areas.Golfy.Models { public class Time { public string time { get; set; } public int holes { get; set; } public int slots_available { get; set; } public decimal? price { get; set; } public int? Nextcourseid { get; set; } public bool ShouldSerializeNextcourseid { get { return this.Nextcourseid != null; } } public bool? allow_extra { get; set; } public bool ShouldSerializeallow_extra { get { return this.allow_extra != null; } } } } ``` ``` namespace Booking.Areas.Golfy.Controllers { public class TeetimesController : Controller { // // GET: /Golfy/Teetimes/ public ActionResult Index( string date, int? courseid = null, int? clubid = null, int? holes = null, int? available = null, int? prices = null ) { var DateFrom = DateTime.ParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture); Teetimes r = BookingManager.GetBookings(new Code.Classes.Params.ParamGetBooking() { ClubID = clubid , DateFrom = DateFrom , DateTo = DateFrom.AddDays(1) , GroundID = courseid }); return Json(r, JsonRequestBehavior.AllowGet); } } } ``` The webservice above returns a json string with several intance of Time. I'd like properties Nextcourseid and allow_extra to be left out of the output when their values are null. I tried ShouldSerializeXxx but it doesn't seems to work. FYI: I also tried [ScriptIgnore] which work but isn't conditional.

Original source