2009-07-24 29 views
9

私はguidをラップするC#の構造体を持っています。 DataContractJsonSerializerを使用して、そのクラスのインスタンスを含むオブジェクトをシリアル化しています。私は直接GUIDを使用していたとき、それはプレーンな文字列としてシリアライズされましたが、現在は名前と値のペアとしてシリアル化されています。ここではNUnitのテストだと、問題を示すコードをサポート:DataContractJsonSerializerをオブジェクトとして文字列としてシリアル化するにはどうすればよいですか?

private static string ToJson<T>(T data) 
    { 
     DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof (T)); 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      serializer.WriteObject(ms, data); 
      return Encoding.Default.GetString(ms.ToArray()); 
     } 
    } 

    [Serializable] 
    private class ID 
    { 
     private Guid _value; 

     public static explicit operator ID(Guid id) 
     { 
      return new ID { _value = id }; 
     } 

     public static explicit operator Guid(ID id) 
     { 
      return id._value; 
     } 
    } 

    [Test] 
    public void IDShouldSerializeLikeGuid() 
    { 
     Guid guid = Guid.NewGuid(); 
     ID id = (ID) guid; 
     Assert.That(ToJson(id), Is.EqualTo(ToJson(guid))); 
    } 

とテストランナー出力:

NUnit.Framework.AssertionException: Expected string length 38 but was 49. Strings differ at index 0. 
    Expected: ""7511fb9f-3515-4e95-9a04-06580753527d"" 
    But was: "{"_value":"7511fb9f-3515-4e95-9a04-06580753527d"}" 
    -----------^ 

は、どのように私はプレーンな文字列として私の構造体をシリアル化し、私のテストに合格するのですか?

答えて

10

JSONが本当に必要ないように見えますが、文字列表現が必要です。その場合、私はこのようなインターフェイスを作成します。

interface IStringSerialized 
{ 
    String GetString(); 
} 

あなたIDタイプ(と同様の要件を持っている他のすべてのタイプ)で、このインタフェースを実装します。

[Serializable] 
class ID : IStringSerialized 
{ 
    private Guid _value; 

    public static explicit operator ID(Guid id) 
    { 
     return new ID { _value = id }; 
    } 

    public static explicit operator Guid(ID id) 
    { 
     return id._value; 
    } 

    public string GetString() 
    { 
     return this._value.ToString(); 
    } 
} 

そして、これらの特殊なケースを処理するために、あなたのシリアル化の方法を変更します。

private static string ToJson<T>(T data) 
{ 
    IStringSerialized s = data as IStringSerialized; 

    if (s != null) 
     return s.GetString(); 

    DataContractJsonSerializer serializer 
       = new DataContractJsonSerializer(typeof(T)); 

    using (MemoryStream ms = new MemoryStream()) 
    { 
     serializer.WriteObject(ms, data); 
     return Encoding.Default.GetString(ms.ToArray()); 
    } 
} 
+0

問題を明確にするためにいくつかの複雑さが省かれましたが、実際のアプリケーションでは、これはリストを含む包含オブジェクトのコンテキスト内にあります。実際のコードでは、["_value": "guid1"}、{"_value": "guid2"}ではなく["guid1"、 "guid2"]を生成します。残念ながら、そのアプローチは私のためには機能しません。しかし、アイデアをありがとう! –

+7

デフォルトのエンコーディングを使用しないでください。ANSI以外の文字が壊れます。私は現在、携帯電話のプッシュメッセージを扱っています。あなたのコードは他の言語を扱うことができるはずです。代わりに、UTF8を使用します。 戻り値Encoding.UTF8.GetString(ms.ToArray()); – midspace

0

は、キー、値の肥大化の問題を防ぐことができますJavaScriptSerializerクラスを使用してみてください。

+1

しかし、シリアル化したいオブジェクト(emitdefaultvalueなど)にあるすべてのデータコントラクト属性が失われます。 – silver

関連する問題