Deserializing JSON to a .NET Object

Generally in .NET MVC you would use the default model binders to deserialize JSON to a .NET object. However, there are some cases, involving “complex” collections, where this becomes a bit tedious to do. Microsoft provides a few ways around this, but none are satisfactory. Unlike the default model binders, the JavaScriptSerializer provides support for deserializing JSON to a .NET object with complex collections.

Take the following simple class and method signature for example:

// simple class
public class SaveInformation
{
    public string Name { get; set; }
    public Dictionary<string, List<SaveItem>> Components { get; set; }
}

// method signature
public ActionResult Save(SaveInformation saveInformation)

Below I’ve included some simple JSON that we will pass to .NET via AJAX:

{"SaveToSession":false,"Name":"My Stupendous Thing","Components":{"Component1":[{"ProductId":"1234"}]}}

We are passing the JSON to .NET using AJAX with the “application/json” contentType. Because we are using the “application/json” contentType, .NET will automatically call the JsonValueProviderFactory and map the information over to our SaveInformation model. It seems pretty straight forward, the Save method will receive a SaveInformation object when it is called.

Not so straightforward unfortunately, the Save method does receive a SaveInformation object. If we inspect our SaveInformation object we see the Name is populated perfectly fine, but the Components dictionary ends up being null.

The reason for this? It seems that the JsonValueProviderFactory doesn’t fully support pure JSON syntax. In order for .NET to properly parse a complex collection, you actually have to give it a numerical index.

From http://msdn.microsoft.com/en-us/magazine/hh781022.aspx:

Though it’s somewhat counterintuitive, JSON requests have the same requirements—they, too, must adhere to the form post naming syntax. Take, for example, the JSON payload for the previous UnitPrice collection. The pure JSON array syntax for this data would be represented as:

[
    { "Code": "USD", "Amount": 100.00 },
    { "Code": "EUR", "Amount": 73.64 }
]

However, the default value providers and model binders require the data to be represented as a JSON form post:

{
    "UnitPrice[0].Code": "USD",
    "UnitPrice[0].Amount": 100.00,

    "UnitPrice[1].Code": "EUR",
    "UnitPrice[1].Amount": 73.64
}

I know right? It was hard for me to read this as well due to the anime-sized tears in my normal-sized eyes. The problem is, no browser I know of has a JSON.serializeForDotNet function. So this leaves us with two options, make our own JSON serializer, or make our own ValueProvider/ModelBinder. Neither of these options sounded very appealing to me, so I went with the hidden third option. Pass in a string 🙂

You can use the JavaScriptSerializer class, located in System.Web.Script.Serialization, to deserialize JSON information and, as an added bonus, it actually handles properly formatted pure JSON!

So, the new method looks like this. We pass in a string value and deserialize it using the JavaScriptSerializer. Now we receive a SaveInformation object with a fully populated Components dictionary.

public ActionResult Save(string saveInformation)
{
    // instantiate a JavaScriptSerializer
    JavaScriptSerializer serializer = new JavaScriptSerializer();

    // use the JavaScriptSerializer to deserialize our json into the expected object
    SaveInformation saveInformationObject = serializer.Deserialize<SaveInformation>(saveInformation);

Taco Bell Removes the Enchirito from Menu

**EDIT 09/20/2013 **

I recently went back to Taco Bell. As it turns out they have put the Enchirito back on the menu. When I asked why, they told me that a lot of people were unhappy and wanted it back. So good work people!

**END EDIT**

Oh Taco Bell. You have done this to me before and you are doing it to me again. When are you going to learn that taking things off your menu is a BAD thing? It is especially bad when you “take” something off the menu and replace it with the same thing albeit more expensive.

A couple of years ago Taco Bell removed the Nacho Cheese Chalupa from it’s menu. (It was probably a couple of years ago although it could’ve been more recently). This made me mad. Let me tell you what I say when I order from Taco Bell. “Hi Taco Bell Person, I’d like 2 bean burritos, a Nacho Cheese Chalupa and an Enchirito”. That’s it! That is what I always had. So imagine my surprise when one day I say my normal order and the response from the other end is “We don’t sell Nacho Cheese Chalupas anymore.” And so I said, “What?…”.

What?...
What?…

Well that was a bad day. But I quickly learned how to get around it by being a super annoying customer. That’s right, my future orders went a little like this.

I’d like two bean burritos, a Nacho Cheese Chalupa, and an Enchirito please.
We don’t sell Nacho Cheese Chalupa’s anymore.
Oh really…? Hrmmm. Well then I would like a Supreme chalupa with no sour cream.
No sour cream?
Yes. No sour cream. Oh and can you add Nacho Cheese to that too?
A Supreme Chalupa with no sour cream and nacho cheese?
Yes.

So, in case you are wondering how to get a Nacho Cheese Chalupa, that’s how.

So… same story no happy ending yet. Today I go to Taco Bell and I order my order. This time they say “We don’t sell enchiritos anymore”. And so I said “What?…”

What?...
What?…

So, as it turns out, they are selling Enchiritos, they’ve just renamed them and made them more expensive. They are now called “Smothered Burritos” and they come with Sourcream on them in addition to the normal stuff. Can you say argggggg? I can. You should try it, I think you probably could.

I’m sure I’m not the only one who thinks it’s LAME to rename an item on your menu and make it more expensive. Then again I guess they can do what they want to do… be stupid.