2009-07-24 12 views
9

Ho una struttura in C# che racchiude un guid. Sto usando DataContractJsonSerializer per serializzare un oggetto contenente un'istanza di quella classe. Quando stavo usando un guid direttamente, è stato serializzato come una stringa semplice, ma ora è serializzato come una coppia nome/valore. Ecco un test NUnit e codice di supporto che illustra il problema:Come posso rendere serializzato un oggetto DataContractJsonSerializer come una stringa?

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))); 
    } 

E l'uscita di test runner:

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"}" 
    -----------^ 

Come faccio a serializzare il mio struct come una stringa normale e far passare la mia prova?

risposta

10

In questo caso sembra che tu non voglia veramente JSON, vuoi una rappresentazione di stringa. In tal caso vorrei creare un'interfaccia simile a questo:

interface IStringSerialized 
{ 
    String GetString(); 
} 

implementare questa interfaccia del tipo di ID (e tutti gli altri tipi che hanno esigenze simili).

[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(); 
    } 
} 

quindi modificare il metodo di serializzazione per gestire questi casi particolari:

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

Ho omesso un po 'di complessità per chiarire il problema, ma nella vera applicazione questo è nel contesto di un oggetto contenitore che contiene un elenco . Voglio che il codice reale produca ["guid1", "guid2"], non [{"_value": "guid1"}, {"_value": "guid2"}]. Quindi, sfortunatamente, questo approccio non funzionerebbe per me. Grazie comunque per l'idea! –

+7

Non utilizzare la codifica predefinita, poiché corrompe qualsiasi carattere non ANSI. Attualmente mi occupo di messaggi push per cellulari. Il tuo codice dovrebbe essere in grado di gestire altre lingue. Utilizzare invece, UTF8. return Encoding.UTF8.GetString (ms.ToArray()); – midspace

0

Provare a utilizzare il JavaScriptSerializer Classe impedirà il problema gonfiare chiave, valore.

+1

ma poi perderai tutti gli attributi dei contratti dati che hai in oggetto oggetto che desideri serializzare (come emitdefaultvalue) – silver

Problemi correlati