¿Cómo serializo un tipo anónimo C # en una cadena JSON?

162

Estoy intentando usar el siguiente código para serializar un tipo anónimo a JSON:

var serializer = new DataContractJsonSerializer(thing.GetType());
var ms = new MemoryStream();
serializer.WriteObject(ms, thing);
var json = Encoding.Default.GetString(ms.ToArray()); 

Sin embargo, obtengo la siguiente excepción cuando se ejecuta esto:

El tipo '<> f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]' no se puede serializar. Considere marcarlo con el atributo DataContractAttribute y marcar todos los miembros que desea serializar con el atributo DataMemberAttribute. Consulte la documentación de Microsoft .NET Framework para otros tipos compatibles.

No puedo aplicar atributos a un tipo anónimo (que yo sepa). ¿Hay otra forma de hacer esta serialización o me falta algo?

JC Grubbs
fuente

Respuestas:

159

Pruebe el JavaScriptSerializer en lugar del DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);
Nick Berardi
fuente
17
Trackback, parece que fue desaprobado en SP1.
Biswanath
77
para algo tan obscuro, parece estar siendo utilizado en muchos nuevos marcos de Microsoft, incluido MVC. aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi el
1
¿Cómo incluyo este proyecto ia non-asp.net (aplicación de consola)?
Alxandr
44
@Alxandr: necesitaría hacer referencia System.Web.Extensions.dlly agregar una using System.Web.Script.Serialization;declaración.
randomguy
1
El problema de @randomgui fue que el tipo de salida del proyecto se estableció en perfil de cliente.
Alxandr
75

Como otros han mencionado, Newtonsoft JSON.NET es una buena opción. Aquí hay un ejemplo específico para la serialización JSON simple:

return JsonConvert.SerializeObject(
    new
    {
       DataElement1,
       SomethingElse
    });

He encontrado que es una biblioteca muy flexible y versátil.

Matthew Nichols
fuente
14

Puede probar mi ServiceStack JsonSerializer , es el serializador .NET JSON más rápido en este momento. Admite la serialización de DataContract, cualquier tipo de POCO, interfaces, objetos enlazados tarde, incluidos los tipos anónimos, etc.

Ejemplo básico

var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = customer.ToJson();
var fromJson = json.FromJson<Customer>(); 

Nota: Solo use Microsofts JavaScriptSerializer si el rendimiento no es importante para usted, ya que he tenido que dejarlo fuera de mis puntos de referencia, ya que es hasta 40x-100x más lento que los otros serializadores JSON.

mythz
fuente
77
Estoy usando MS JavaScriptSerializer en la pila MVC3 para serializar objetos con pequeñas cantidades de datos. Es bastante rápido en estos casos, tomar menos de un milisegundo para hacer lo que necesito. La consulta DB en sí misma tarda 50x-100x más tiempo, por lo que no es realmente un cuello de botella significativo en mi situación.
Brian
2
La optimización prematura es un ... Bueno, ya sabes.
Mathias Lykkegaard Lorenzen
1
¡El enlace "serializador más rápido de .NET JSON" es 404ing! Además, esta respuesta tiene más de 5 años y medio. ¿Tiene una actualización sobre el rendimiento de varios serializadores .NET JSON?
ErikE
11

Tenga en cuenta que esto es de 2008. Hoy diría que el serializador debería estar integrado y que probablemente pueda usar los atributos swagger + para informar a los consumidores sobre su punto final y los datos de retorno.


Yo diría que no deberías estar serializando un tipo anónimo . Sé la tentación aquí; desea generar rápidamente algunos tipos desechables que solo se utilizarán en un entorno de tipo flexible, también conocido como Javascript, en el navegador. Aún así, crearía un tipo real y lo decoraría como serializable. Entonces puede escribir fuertemente sus métodos web. Si bien esto no importa un ápice para Javascript, sí agrega algo de autodocumentación al método. Cualquier programador con experiencia razonable podrá mirar la firma de la función y decir: "¡Oh, este es el tipo Foo! Sé cómo debería verse en JSON".

Dicho esto, puede intentar JSON.Net para hacer la serialización. No tengo idea si funcionará

Jason Jackson
fuente
3
JSON.Net funciona bien. Yo diría que no deberías :), creo que es bastante legítimo en muchos casos.
abril April
2
Después de ver los tipos de "tirar" que se usan en MVC, puedo ver algunos usos convincentes. Creo que es una herramienta muy útil para tener en su caja de herramientas .Net.
Matthew Whited
12
Este es un punto que también he suavizado, especialmente en el caso de los tipos de solo consumo. Pero si el objeto está haciendo un viaje de regreso al servidor, o si se usa en más de una ubicación, todavía creo que crear un tipo dará como resultado menos problemas.
Jason Jackson
La deserialización del estilo DataContract no maneja bien los tipos polimórficos. Tienes que escribir tu propio deserializador. Demasiado mantenimiento de código.
micahhoover
Un caso de uso en el que la serialización de tipos anónimos es útil son las pruebas unitarias para API web.
howcheng
9

La forma más rápida que encontré fue esta:

var obj = new {Id = thing.Id, Name = thing.Name, Age = 30};
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(obj);

Espacio de nombres: System.Web.Script.Serialization.JavaScriptSerializer

i31nGo
fuente
2
Y para la deserialización:. . myObject dinámico = JsonConvert.DeserializeObject <dynamic> (salida); . . referencia: Newtonsoft.json.dll
i31nGo
2

Podrías usar Newtonsoft.Json.

var warningJSON = JsonConvert.SerializeObject(new {
                warningMessage = "You have been warned..."
            });
Ahmet Arslan
fuente
1

Suponiendo que está utilizando esto para un servicio web, puede aplicar el siguiente atributo a la clase:

[System.Web.Script.Services.ScriptService]

Luego, el siguiente atributo para cada método que debería devolver Json:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

Y establezca el tipo de retorno para que los métodos sean "objeto"

Pablo
fuente
Para un servicio web ASP estándar [ScriptMethod (ResponseFormat = ResponseFormat.Json)] no es necesario en el método, [WebMethod] lo hará. Además, no debe establecer el tipo de retorno en objeto, puede y debe escribirse fuertemente con un tipo no complejo (es decir, puede ser serializado).
fila1
-1
public static class JsonSerializer
{
    public static string Serialize<T>(this T data)
    {
        try
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream();
            serializer.WriteObject(stream, data);
            string jsonData = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
            stream.Close();
            return jsonData;
        }
        catch
        {
            return "";
        }
    }
    public static T Deserialize<T>(this string jsonData)
    {
        try
        {
            DataContractJsonSerializer slzr = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
            T data = (T)slzr.ReadObject(stream);
            stream.Close();
            return data;
        }
        catch
        {
            return default(T);
        }
    }
}
harryovers
fuente
Esto no serializa tipos anónimos según la pregunta
Mark Sowul