2009-07-24 9 views
9

Tengo una estructura en C# que envuelve un guid. Estoy usando DataContractJsonSerializer para serializar un objeto que contiene una instancia de esa clase. Cuando estaba usando un guid directamente, se serializó como una cadena simple, pero ahora se serializa como un par nombre/valor. Aquí está una prueba de NUnit y el código de apoyo que muestra el problema:¿Cómo puedo hacer que DataContractJsonSerializer serialice un objeto como una cadena?

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

Y la salida corredor de prueba:

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

¿Cómo serializar mi estructura como una cadena simple y hacer mi prueba?

Respuesta

10

En este caso, parece que realmente no desea JSON, quiere una representación de cadena. En ese caso, me gustaría crear una interfaz de esta manera:

interface IStringSerialized 
{ 
    String GetString(); 
} 

implementar esta interfaz de su tipo de ID (y todos los otros tipos que tienen requisitos similares).

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

a continuación, modificar su método de serialización para manejar estos casos especiales:

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

Olvidé algunas complejidades para aclarar el problema, pero en la aplicación real esto está en el contexto de un objeto que contiene una lista . Quiero que el código real produzca ["guid1", "guid2"], no [{"_value": "guid1"}, {"_value": "guid2"}]. Desafortunadamente, ese enfoque no funcionará para mí. ¡Gracias por la idea! –

+7

No utilice la codificación predeterminada, ya que dañará los caracteres que no sean ANSI. Actualmente estoy lidiando con mensajes de inserción de teléfonos móviles. Tu código debería poder tratar con otros idiomas. Use en su lugar, UTF8. return Encoding.UTF8.GetString (ms.ToArray()); – midspace

0

Trate de usar la clase JavaScriptSerializer que evitará la emisión hinchazón clave, valor.

+1

pero luego perderá todos los atributos de contratos de datos que tiene en el objeto que desea serializar (como emitir valor predeterminado) – silver

Cuestiones relacionadas