WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

Dictionary の JSON シリアライズ

by WebSurfer 2018年6月2日 18:56

Dictionary<TKey, TValue> クラスのオブジェクトを、ASP.NET MVC の Controller クラスの Json メソッドなどで使われている JavaScriptSerializer クラスを用いて JSON 文字列にシリアライズするとどうなるかという話を書きます。

Dictionary の JSON シリアライズ

例えば、以下のような Controller のアクションメソッドで Dictionary<string, Car> オブジェクトを作って Json メソッドで JSON 文字列にシリアライズしてみます。(注: TKey は JSON の「名前:値」ペアの「名前」になるので string 型にする必要があるようです。実際 int 型ではエラーになりました)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Mvc5App.Controllers
{
  public class Car
  {
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public float Price { get; set; }
  }

  public class HomeController : Controller
  {        
    public ActionResult JsonDictionary()
    {
      Dictionary<string, Car> dic = 
                          new Dictionary<string, Car>()
      {
        { "Car1", new Car() { Make="Audi",
            Model="A4", Year=1995, Price=2995f } },
        { "Car2", new Car() { Make="Ford",
            Model="Focus", Year=2002, Price=3250f } },
        { "Car3", new Car()  {Make="BMW",
            Model ="503i",Year=1997,Price=1995f } }
      };            

      return Json(dic);
    }
  }
}

上のアクションメソッドをブラウザから POST 要求すると、以下の JSON 文字列が応答として返ってきます。(注: POST 要求するのは、Json メソッドはデフォルトでは GET 要求を拒否するからです)

{
"Car1":{"Make":"Audi","Model":"A4","Year":1995,"Price":2995},
"Car2":{"Make":"Ford","Model":"Focus","Year":2002,"Price":3250},
"Car3":{"Make":"BMW","Model":"503i","Year":1997,"Price":1995}
}

つまり、JSON の「名前:値」ペアとして、Dictionary<TKey, TValue> の TKey が「名前」に、 TValue(Car の JavaScript オブジェクトの JSON 文字列) が「値」に設定され、そのペアが Dictionary の要素の数(上の例では 3 つ)並べられた JSON 文字列になります。

知ってました? 実は自分は知らなかったです。(汗) Dictionary<TKey, TValue> なんて JSON にシリアライズできないと思ってました。(恥)

デシリアライズも、もちろんできるようです。例えば、jQuery alax を利用して上記アクションメソッドを呼び出すと、自動的に JSON 文字列が JavaScript オブジェクトにデシリアライズされ、コールバックの引数として渡されます。

以下の例を見てください、function(data) ... の引数 data にデシリアライズされた JavaScript オブジェクトが渡されます。それを jsonresult という id を持つ div 要素の中に書き込んだのが上の画像です。

function jsonDictionary() {
    $.ajax({
        type: 'POST',
        url: '/home/jsonDictionary'
    })
    .done(function (data) {
        $("#jsonresult").empty();
        $.each(data, function (index, car) {
            $('#jsonresult').append(
                '<p><strong>' + index + '</strong></p>' +
                '<p>' + car.Make + ' ' + car.Model +
                ', Year: ' + car.Year +
                ', Price: $' + car.Price + '</p>');
        });
    })
    .fail(function (jqXHR, textStatus, errorThrown) {
        $("#jsonresult").text('textStatus: ' + textStatus +
          ', errorThrown: ' + errorThrown);
    })
}

上のコードの例では、jQuery の jQuery.each() メソッドを使っていますが、JavaScript の for ... in ループを使って同じ処置を行う例も書いておきます。

for (var key in data) {
    $('#jsonresult').append(
        '<p><strong>' + key + '</strong></p>' +
        '<p>' + data[key].Make + ' ' + data[key].Model +
        ', Year: ' + data[key].Year +
        ', Price: $' + data[key].Price + '</p>');
}

元の .NET Framework の Dictionary<string, Car> オブジェクトにも JavaScriptSerializer や Json.NET (Newtonsoft.Json) を使ってデシリアライズできます。

string json = "上の JSON 文字列";

// JavaScriptSerializer
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, Car> dic =
    serializer.Deserialize<Dictionary<string, Car>>(json);

// Json.NET (Newtonsoft.Json)
Dictionary<string, Car> dic =
  JsonConvert.DeserializeObject<Dictionary<string, Car>>(json);

ただし、DataContractJsonSerializer では、自分が試した限りですが、ダメでした。何かやり方はあるのかもしれませんが。

Tags: ,

JavaScript

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2018年8月  >>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar