9

I've got a dictionary<string,string> as part of my view model. What I'm trying to do is cycle this object and output it as a json object. My reason for this is so I can localise my client script files correctly.

The output for this needs to look something like

var clientStrings = {"test":"yay","goodBye":"Nah"};

Any ideas how to achieve this correctly.

Thanks in advance.

Rudi
  • 3,124
  • 26
  • 35
RubbleFord
  • 7,456
  • 9
  • 50
  • 80

3 Answers3

15

It's built into MVC. Just return Json(yourobject).

Matt Sherman
  • 8,298
  • 4
  • 37
  • 57
10

Considering you are on mvc 3 you'll have access to JavaScriptSerializer. You should be able to do the following:

JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize((object)yourDictionary);

This will serialize your dictionary to json. You may want to do this in the controller before sending the ViewData to the view to render.

Jeremy B.
  • 9,168
  • 3
  • 45
  • 57
8

Also you can integrate the free Json.NET library within your code.

This library does not suffer the problems JavascriptSerializer has like the circular reference problem.

This is a sample using the library to output JSON from a controller action

public virtual ActionResult ListData() {
    Dictionary<string, string> openWith = new Dictionary<string, string>();
    openWith.Add( "txt", "notepad.exe" );
    openWith.Add( "bmp", "paint.exe" );
    openWith.Add( "dib", "paint.exe" );
    openWith.Add( "rtf", "wordpad.exe" );

    JsonNetResult jsonNetResult = new JsonNetResult();
    jsonNetResult.Formatting = Formatting.Indented;
    jsonNetResult.Data = openWith;
    return jsonNetResult;
}

If you execute this action you will get the following results

{
  "txt": "notepad.exe",
  "bmp": "paint.exe",
  "dib": "paint.exe",
  "rtf": "wordpad.exe"
}

JsonNetResult is a simple custom wrapper class around the functionalities of the Json.NET library.

public class JsonNetResult : ActionResult
{
    public Encoding ContentEncoding { get; set; }
    public string ContentType { get; set; }
    public object Data { get; set; }

    public JsonSerializerSettings SerializerSettings { get; set; }
    public Formatting Formatting { get; set; }

    public JsonNetResult() {
        SerializerSettings = new JsonSerializerSettings();
    }

    public override void ExecuteResult( ControllerContext context ) {
        if ( context == null )
            throw new ArgumentNullException( "context" );

        HttpResponseBase response = context.HttpContext.Response;

        response.ContentType = !string.IsNullOrEmpty( ContentType )
            ? ContentType
            : "application/json";

        if ( ContentEncoding != null )
            response.ContentEncoding = ContentEncoding;

        if ( Data != null ) {
            JsonTextWriter writer = new JsonTextWriter( response.Output ) { Formatting = Formatting };

            JsonSerializer serializer = JsonSerializer.Create( SerializerSettings );
            serializer.Serialize( writer, Data );

            writer.Flush();
        }
    }
}
Lorenzo
  • 29,081
  • 49
  • 125
  • 222
  • I'm not sure JSON.NET is able to do Dictionaries, can you confirm that it can, as that is what RubbleFord is asking – Jeremy B. Dec 06 '10 at 18:13
  • It works seamlessly :) I have edited my answer for your pleasure – Lorenzo Dec 06 '10 at 20:09
  • @Lorenzo, why use this over the built in Json(xxx)? Any advantages? – Adam Tuliper Aug 29 '11 at 17:10
  • @Adam Tuliper: I cant confirm it for sure, but I think that internally `Json(xxx)` uses `JavaScriptSerializer` which suffers of the circular reference problem which you can read about it [here](http://stackoverflow.com/questions/2002940/json-and-circular-reference-exception) and [here](http://msdn.microsoft.com/en-us/library/bb292287.aspx). My answer is just an addendum to the accepted answer which is 100% correct – Lorenzo Aug 29 '11 at 20:31
  • 1
    @AdamTuliper: JSON.NET has the possibility of whitelisting which properties you want to output via the JsonProperty attribute, see http://stackoverflow.com/questions/2546138/deserializing-json-data-to-c-sharp-using-json-net. Additionally, JSON.NET can serialize a property having a getter but no setter, which the WCF DataContract JSON serializer can't. – Thomas Lundström Oct 24 '11 at 12:06
  • @ThomasLundström thanks - good to know. JsonResult can though just use the ScriptIgnore attribute to exclude fields on what should already be a limited ViewModel. By design though, the json result should be limited to that ViewModel that is being returned and 'ideally' wouldn't have these fields although I realize in practice this isn't always the case : ) – Adam Tuliper Oct 24 '11 at 16:06