Paradigm Shift Design

ISHITOYA Kentaro's blog.

JSONとクラスのマッピング

結局、JSONとオブジェクトのマッピングにはてこずりました。
手こずった挙句に、
Json.NET
Silverlightにも対応していることを思い出し、ショックを受けていたわけですが、とりあえずできたので書いておきます。

を参考に、モデルクラスを

using System;
using System.Net;
using System.Windows;        
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Collections; 
using System.Collections.Generic; 
using System.Json;
using com.semcode.commons; 
using com.semcode.tmboard.db.entity;

namespace com.semcode.tmboard.db.entity
{
    [DataContract]
    public class StrokeGroup : AbstractHashableObject
    {
        [DataMember(Name="id")]
        public int Id { get; set; }

        [DataMember(Name="deviceTypeId")]
        public int DeviceTypeId { get; set; }

        [DataMember(Name="userId")]
        public int UserId { get; set; }

        public StrokeGroup()
        {
        }
    }
}

とかって定義します。DataContractアノテーション?っていうの?.NETの世界でなんていうのか知らないからアノテーションと言いますが、をクラスにつけて、メンバーにDataMemberアノテーションをつければモデルクラスの準備は完了です。
両方ともSystem.Runtime.Serializationパッケージに入ってます。


このとき、親クラス、AbstractHashableObject自体に、DataContractアノテーションがついていないと、

{System.Runtime.Serialization.InvalidDataContractException: 型 'com.semcode.tmboard.db.dto.SessionDto' は、DataContractAttribute も SerializableAttribute も設定されていない型からは継承できません。基本型 'com.semcode.commons.AbstractHashableObject' に DataContractAttribute または SerializableAttribute を設定するか、これらを派生型から削除してください。

という例外が飛びます。アノテーションをつければ大丈夫。


で、上のリンクには、DataContractJsonSerializerというのを使えと書いてあるのだけれど、そいつが見つからない。名前は、System.Runtime.Serialization.JSON.DataContractJsonSerializerなのに、System.Runtime.Serialization.JSONパッケージに入っていない。
なんだそりゃ、と言ってググると、

名前空間 : System.Runtime.Serialization.Json
アセンブリ : System.ServiceModel.Web (System.ServiceModel.Web.dll 内)

だそうで。分りにくすぎる!


で、

/// <summary>
/// アップロード完了時のイベントハンドラ
/// </summary>
/// <param name="sender">送信者</param>
/// <param name="e">メッセージ</param>
protected void client_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
    try
    {
        MemoryStream stream = 
            new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
        DataContractJsonSerializer ser = 
            new DataContractJsonSerializer(typeof(SessionResponse));
        stream.Position = 0;
        SessionResponse session = (SessionResponse)ser.ReadObject(stream);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

とすればいいようです。ちゃんとオブジェクトにマッピングされました。
めでたしめでたし。