Come posso serializzare un tipo anonimo C # su una stringa JSON?


162

Sto tentando di utilizzare il seguente codice per serializzare un tipo anonimo su JSON:

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

Tuttavia, ottengo la seguente eccezione quando viene eseguita:

Digitare '<> f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]' non può essere serializzato. Valuta di contrassegnarlo con l'attributo DataContractAttribute e di contrassegnare tutti i suoi membri che desideri serializzare con l'attributo DataMemberAttribute. Vedere la documentazione di Microsoft .NET Framework per altri tipi supportati.

Non riesco ad applicare gli attributi a un tipo anonimo (per quanto ne so). C'è un altro modo di fare questa serializzazione o mi sto perdendo qualcosa?

Risposte:


159

Prova JavaScriptSerializer invece di DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);

17
Trackback, sembra che sia stato deprecato in SP1.
Biswanath,

7
per qualcosa di così obsoleto, sembra essere utilizzato in molti nuovi framework Microsoft, incluso MVC. aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi

1
Come posso includere questo progetto ia non-asp.net (applicazione console)?
Alxandr,

4
@Alxandr: dovresti fare riferimento System.Web.Extensions.dlle aggiungere using System.Web.Script.Serialization;un'istruzione.
randomguy

1
Il problema @randomgui era che il tipo di output del progetto era impostato sul profilo client.
Alxandr,

75

Come altri hanno già detto, Newtonsoft JSON.NET è una buona opzione. Ecco un esempio specifico per la semplice serializzazione JSON:

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

Ho trovato una libreria molto flessibile e versatile.


14

Puoi provare il mio ServiceStack JsonSerializer al momento è il serializzatore JSON .NET più veloce . Supporta la serializzazione di DataContract, qualsiasi tipo di POCO, interfacce, oggetti associati in ritardo, inclusi tipi anonimi, ecc.

Esempio di base

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

Nota: utilizzare il JavaScriptSerializer di Microsoft solo se le prestazioni non sono importanti per te poiché ho dovuto lasciarle fuori dai miei benchmark poiché è fino a 40x-100x più lenta degli altri serializzatori JSON.


7
Sto usando MS JavaScriptSerializer sullo stack MVC3 per serializzare oggetti con piccole quantità di dati. In questi casi è piuttosto veloce, impiegando meno di un millisecondo per fare ciò di cui ho bisogno. La query DB stessa impiega 50x-100x in più, quindi non è un collo di bottiglia significativo nella mia situazione.
Brian,

2
L'ottimizzazione prematura è un ... Beh, lo sai.
Mathias Lykkegaard Lorenzen,

1
Il collegamento "serializzatore .NET JSON più veloce" è 404ing! Inoltre, questa risposta ha più di 5 anni e mezzo. Hai un aggiornamento sulle prestazioni di vari serializzatori JSON .NET?
ErikE

11

Si noti che questo è del 2008. Oggi direi che il serializzatore dovrebbe essere integrato e che probabilmente è possibile utilizzare gli attributi swagger + per informare i consumatori sull'endpoint e i dati di restituzione.


Direi che non dovresti serializzare un tipo anonimo . Conosco la tentazione qui; vuoi generare rapidamente alcuni tipi usa e getta che verranno semplicemente utilizzati in un ambiente di tipo vagamente noto come Javascript nel browser. Tuttavia, vorrei creare un tipo reale e decorarlo come serializzabile. Quindi puoi digitare fortemente i tuoi metodi web. Anche se questo non ha importanza per un iota per Javascript, aggiunge un po 'di autocertificazione al metodo. Qualsiasi programmatore con ragionevole esperienza sarà in grado di guardare la firma della funzione e dire: "Oh, questo è il tipo Foo! So come dovrebbe apparire in JSON."

Detto questo, potresti provare JSON.Net per eseguire la serializzazione. Non ho idea se funzionerà


3
JSON.Net funziona perfettamente. Direi che non dovresti :), penso che sia abbastanza legittimo in molti casi.
aprile

2
Dopo aver visto i tipi "usa e getta" utilizzati in MVC, posso vedere alcuni usi convincenti. Penso che sia uno strumento molto utile da avere nella tua cassetta degli attrezzi .Net.
Matthew Whited,

12
Questo è un punto su cui ho anche ammorbidito, soprattutto nel caso dei tipi esclusivamente a consumo. Ma se l'oggetto sta effettuando un viaggio di ritorno al server o viene utilizzato in più di una posizione, credo comunque che la creazione di un tipo comporterà meno problemi.
Jason Jackson,

La serializzazione in stile DataContract non gestisce bene i tipi polimorfici. Devi scrivere il tuo de-serializzatore. Troppa manutenzione del codice.
micahhoover,

Un caso d'uso in cui la serializzazione di tipi anonimi è utile sono i test unitari per le API Web.
howcheng

9

Il modo più veloce che ho trovato è stato questo:

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

Spazio dei nomi: System.Web.Script.Serialization.JavaScriptSerializer


2
E per la deserializzazione:. . dynamic myObject = JsonConvert.DeserializeObject <dynamic> (output); . . riferimento: Newtonsoft.json.dll
i31nGo

2

Puoi usare Newtonsoft.Json.

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

1

Supponendo che tu lo stia utilizzando per un servizio Web, puoi semplicemente applicare il seguente attributo alla classe:

[System.Web.Script.Services.ScriptService]

Quindi il seguente attributo a ciascun metodo che dovrebbe restituire Json:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

E imposta il tipo restituito per i metodi come "oggetto"


Per un servizio Web ASP standard [ScriptMethod (ResponseFormat = ResponseFormat.Json)] non è necessario sul metodo, [WebMethod] lo farà. Inoltre, non è necessario impostare il tipo restituito su object, può e deve essere fortemente tipizzato con un tipo non complesso (ovvero può essere serializzato).
row1

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

Questo non serializza i tipi anonimi secondo la domanda
Mark Sowul,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.