1

I've a problem converting a dictonairy to JSON.NET. I'm sure i'm missing some points. Also my experience in working with JSON is small and I mostly did it from php not from c#.

It adds &qout i'm missing

//GENERAL NOTE: IT's a school project (so not much focus on security)

//C#

public ActionResult GetChartData(string startDate, string endDate)
{
    Dictionary<Movie, double> profitList =  //Gets data from repository

    //in the json list i want the movie names not the objects so I make another dictonairy to convert to json
    Dictionary<string, double> plist = profitList.ToDictionary(keyValuePair => keyValuePair.Key.Title, keyValuePair => keyValuePair.Value);

    //Code from other stackoverflow post
    //http://stackoverflow.com/questions/3739094/serializing-deserializing-dictionary-of-objects-with-json-net

    string json = JsonConvert.SerializeObject(plist, Formatting.Indented, new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.All,
        TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
    });

    //ViewModel i Use
    FinancialViewModel viewModel = new FinancialViewModel
    {
        ProfitList = profitList,
        ProfitListJson = json,
        Start = start,
        End = end
    };

    return PartialView("_FinancialPartialView", viewModel);
}



//JS
<script>
     var chart = AmCharts.makeChart("chart_6", {
         "type": "pie",
         "theme": "light",

         "fontFamily": "Open Sans",
         "color": "#888",
         "dataProvider": @Model.ProfitListJson,
        "valueField": "movie", //the name from the movie
        "titleField": "profit", //the profit from the movie
        "exportConfig": {
             menuItems: [
                 {
                     icon: Metronic.getGlobalPluginsPath() + "amcharts/amcharts/images/export.png",
                     format: "png"
                 }
             ]
         }
     });

</script>

This is the result I want to get

"dataProvider": [{
                "movie": "Title of movie 1",
                "profit": Profit of movie 1
            }, {
                "movie": Title 2c",
                "profit": Profit 2
            }],
            "valueField": "movie",
            "titleField": "profit",

The current result I get in the controller while debugging enter image description here

The result in chrome enter image description here

I've tried a lot of other Stackoverflow answers. I don't know what to try anymore.

Thanks so far!

enter image description here

6
  • Are you double-serializing your plist -- serializing it, then embedding the string in a class to be re-serialized? Also, why return both the serialized json of plist and the ProfitList dictionary? Commented Mar 27, 2015 at 15:40
  • @dbc they are both returned cause I use the profitList for data tables in the partial view. I've to check on the other part of your comment. Commented Mar 27, 2015 at 15:45
  • Json.NET won't serialize a dictionary with complex classes as keys. See here. Some workarounds here: How can I serialize/deserialize a dictionary with custom keys using Json.Net?. Commented Mar 27, 2015 at 15:53
  • @dbc he converts it to a Dictionary<string, double> before serializing it. Commented Mar 27, 2015 at 16:05
  • 1
    No, view models aren't automatically serialized so their properties can be of any type. Commented Mar 27, 2015 at 16:45

3 Answers 3

2

In order to get a JSON with movie and profit attributes, you will need to create a DTO (Data Transfer Object) E.g.

public class MovieProfit
{
    public string Title { get; set; }
    public double Profit { get; set; }
}

and then convert your dictionary to a list of this DTO using Linq

List<MovieProfit> plist = profitList.Select(keyValuePair => new MovieProfit() { Title = keyValuePair.Key.Title, Profit = keyValuePair.Value }).ToList();

You will now get the desired JSON on serialization.

With regards to the quotes, it is because you are serializing your objects to a JSON string and passing the string back in the ViewModel. If you pass the object or list of objects back, you will not face this problem.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks so far, looks a lot better now in the controller. Is there a solution to use it in a viewModel? and do I need to worry about the $type in the json viewer (see first image)?
There is no need to worry about the $type, however @Sam has answered how you can remove that. I did not quite understand "Is there a solution to use it in a viewModel?"
sam answered that part. I thought it wasn't possible to use it in a view model. Thanks for the help!
1

First, you should remove the TypeNameHandling = TypeNameHandling.All setting. That's the reason your JSON includes the $type property.

Second, you should use @Html.Raw(Model.ProfitListJson) to render your JSON string without &quot.

Something like this in your View:

var jsonObj = @Html.Raw(Model.ProfitListJson);
var chart = AmCharts.makeChart("chart_6", {
    //...
    "dataProvider": jsonObj,
    //...
});

Something like this in your controller:

string json = JsonConvert.SerializeObject(plist, 
  Formatting.Indented, 
  new JsonSerializerSettings
{
    TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple // I don't think this is needed, but leaving it in in case you had a reason for it
});

3 Comments

Almost there! Thank you! When I add your JsonString example It gives me an error in google chrome for a illegal token. I update the answer with the result in a second
Try removing the single quotes and just use the model value directly. See my updated answer
thanks it works (the data gets correctly in the view). The chart is not drawing but that's a other problem to find out.
0

the answer should be something like this using jobject (newtonsoft.json.linq)

JObject o = new JObject
        (
            new JProperty("DataProvider",
                new JArray(
                    from m in List
                    select new JObject(
                        new JProperty("title",m.Key),
                        new JProperty("profit",m.Value))))
        );

and that is it you can display by using o.tostring()

the output is something like

{
  "DataProvider": [
    {
      "title": "movie1",
      "profit": 2121.0
    },
    {
      "title": "movie2",
      "profit": 47877.0
    }
  ]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.