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

JochemQuery
  • 1,495
  • 2
  • 26
  • 38
  • 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? – dbc Mar 27 '15 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. – JochemQuery Mar 27 '15 at 15:45
  • Json.NET won't serialize a dictionary with complex classes as *keys*. See [here](https://stackoverflow.com/questions/24504245/not-ableto-serialize-dictionary-with-complex-key-using-json-net). Some workarounds here: [How can I serialize/deserialize a dictionary with custom keys using Json.Net?](https://stackoverflow.com/questions/24681873/how-can-i-serialize-deserialize-a-dictionary-with-custom-keys-using-json-net). – dbc Mar 27 '15 at 15:53
  • @dbc he converts it to a Dictionary before serializing it. – Sam Mar 27 '15 at 16:05
  • @Sam - Isn't OP is serializing the original dictionary as `ProfitList = profitList` alongside the `plist` dictionary? – dbc Mar 27 '15 at 16:38
  • 1
    No, view models aren't automatically serialized so their properties can be of any type. – Sam Mar 27 '15 at 16:45

3 Answers3

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.

Praveen Paulose
  • 5,741
  • 1
  • 15
  • 19
  • 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)? – JochemQuery Mar 27 '15 at 15:56
  • 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?" – Praveen Paulose Mar 27 '15 at 16:02
  • sam answered that part. I thought it wasn't possible to use it in a view model. Thanks for the help! – JochemQuery Mar 27 '15 at 16:18
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
});
Sam
  • 4,994
  • 4
  • 30
  • 37
  • 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 – JochemQuery Mar 27 '15 at 16:12
  • Try removing the single quotes and just use the model value directly. See my updated answer – Sam Mar 27 '15 at 16:14
  • thanks it works (the data gets correctly in the view). The chart is not drawing but that's a other problem to find out. – JochemQuery Mar 27 '15 at 16:17
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
    }
  ]
}
Coder1409
  • 523
  • 4
  • 12