How to flatten an ExpandoObject returned via JsonResult in asp.net mvc?

TimDog picture TimDog · Mar 1, 2011 · Viewed 48.1k times · Source

I really like the ExpandoObject while compiling a server-side dynamic object at runtime, but I am having trouble flattening this thing out during JSON serialization. First, I instantiate the object:

dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);

So far so good. In my MVC controller, I want to then send this down as a JsonResult, so I do this:

return new JsonResult(expando);

This serializes the JSON into the below, to be consumed by the browser:

[{"Key":"SomeProp", "Value": SomeValueOrClass}]

BUT, what I'd really like is to see this:

{SomeProp: SomeValueOrClass}

I know I can achieve this if I use dynamic instead of ExpandoObject -- JsonResult is able to serialize the dynamic properties and values into a single object (with no Key or Value business), but the reason I need to use ExpandoObject is because I don't know all of the properties I want on the object until runtime, and as far as I know, I cannot dynamically add a property to a dynamic without using an ExpandoObject.

I may have to sift through the "Key", "Value" business in my javascript, but I was hoping to figure this out prior to sending it to the client. Thanks for your help!

Answer

Mikael Koskinen picture Mikael Koskinen · Dec 6, 2012

Using JSON.NET you can call SerializeObject to "flatten" the expando object:

dynamic expando = new ExpandoObject();
expando.name = "John Smith";
expando.age = 30;

var json = JsonConvert.SerializeObject(expando);

Will output:

{"name":"John Smith","age":30}

In the context of an ASP.NET MVC Controller, the result can be returned using the Content-method:

public class JsonController : Controller
{
    public ActionResult Data()
    {
        dynamic expando = new ExpandoObject();
        expando.name = "John Smith";
        expando.age = 30;

        var json = JsonConvert.SerializeObject(expando);

        return Content(json, "application/json");
    }
}