3

Say I have a class:

public class Cat
{
    public int Hunger {get; set;}
    public int Sleepiness {get; set;}
    public int Usefullness {
      get { throw new DivideByZeroException(); }
    }
}

Is it possible to serialize it as below:

public ActionResult GetMyCat()
{
     Cat c = new Cat()
    {
        Hunger = 10,
        Sleepiness = 10
    };

    return Json(c);
}

I can't modify the "Cat" class. Can I have the MVC JSON Serializer ignore the error that one property threw, (if it threw an error) and just give me an empty/default value for that property?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
David
  • 15,652
  • 26
  • 115
  • 156
  • Do you *have* to use the built-in JSON serializer? – Ron Beyer Oct 05 '15 at 12:49
  • The problem is, I'm dealing with HUGE poco classes with hundreds of properties. I wouldn't say **have**, but I'd rather not write a serializer for these classes unless it's dynamic. – David Oct 05 '15 at 12:51
  • is it possible to add an attribute to you property? if so you may try, `[JsonIgnore]` – Kishore Sahasranaman Oct 05 '15 at 12:52
  • No, but there are other serializers out there that do a better job, like JSON.NET, and can handle this kind of situation. No need to write your own. – Ron Beyer Oct 05 '15 at 12:52
  • http://stackoverflow.com/questions/18543482/is-there-a-way-to-ignore-get-only-properties-in-json-net-without-using-jsonignor – Ron Beyer Oct 05 '15 at 12:54

3 Answers3

2

Create class extension that will return proper object

public static class CatExtensions
 {
        public static object GetObject(this Cat value)
        {
            return new
            {
                Hunger = value.Hunger,
                Sleepiness = value.Sleepiness
            }
        }
    }
nomail
  • 635
  • 6
  • 21
  • Any way I can do this dynamically? – David Oct 05 '15 at 12:53
  • Actually, you just gave me an idea. I think I know how I can do this dynamically. I'll give it a shot. It's going to be ugly though. – David Oct 05 '15 at 12:55
  • what do you mean by dynamically? Please share what you have in mind :) – nomail Oct 05 '15 at 12:56
  • Say the cat class had five million properties and you were too lazy to write a huge GetObject() function :P I'm thinking about going through the properties by reflection. – David Oct 05 '15 at 12:57
  • @David, It's going to get tricky when you get to your "dynamic exclusion" logic. How would you determine which properties stay and which should be left out of the new object? Personal opinion, if you go with the "new object approach", rather take the shot and create them manually as in nomail's example, this gives you control in the long run IMHO :) – Niels Filter Oct 05 '15 at 13:04
  • do you really need all those five million properties? I mean returning 5mil properties to client doesn't seem very user-friendly – nomail Oct 05 '15 at 13:08
  • Haha, just kidding about that. And about the tricky part, see my answer ;) – David Oct 05 '15 at 13:13
1

Ok, This is ugly, but here is one way:

Cat c = new Cat()
{
    Hunger = 10,
    Sleepiness = 10
};

dynamic dynamicCat = new ExpandoObject();
IDictionary<string, object> dynamicCatExpando = dynamicCat;

Type type = c.GetType();
PropertyInfo[] properties = type.GetProperties();

foreach (PropertyInfo property in properties)
{
    try
    {
        dynamicCatExpando.Add(property.Name, property.GetValue(c, null));
    }
    catch (Exception)
    {
       //Or just don't add the property here. Your call.
        object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
        dynamicCatExpando.Add(property.Name, defaultValue); //I still need to figure out how to get the default value if it's a primitive type.
    }
}

return Content(JsonConvert.SerializeObject(dynamicCatExpando), "application/Json");
David
  • 15,652
  • 26
  • 115
  • 156
0

You could use an external JSON serialization library such as this one and add a custom attribute to skip the value. Or perhaps add a try catch around getting the value and ignoring it when the trap is sprung.

TJHeuvel
  • 12,403
  • 4
  • 37
  • 46