Come posso serializzare un tipo anonimo C # su una stringa JSON?
-
22-07-2019 - |
Domanda
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:
Tipo 'Lt &; & Gt; f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]' non può essere serializzato. Prendi in considerazione la marcatura con DataContractAttribute attributo e contrassegnando tutto ciò membri che si desidera serializzare con Attributo DataMemberAttribute. Vedere Microsoft .NET Framework documentazione per altri supportati tipi.
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?
Soluzione
Prova JavaScriptSerializer invece di DataContractJsonSerializer
JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);
Altri suggerimenti
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.
Puoi provare il mio ServiceStack JsonSerializer è il serializzatore JSON .NET più veloce al momento. Supporta la serializzazione di DataContract, qualsiasi tipo di POCO, interfacce, oggetti associati a ritardo, compresi i 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: usa 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.
Si noti che proviene dal 2008. Oggi vorrei dire che il serializzatore dovrebbe essere integrato e che probabilmente è possibile utilizzare swagger + attributi per informare i consumatori sul proprio endpoint e restituire i dati.
Direi che non dovresti serializzare un tipo anonimo . Conosco la tentazione qui; vuoi generare rapidamente alcuni tipi usa e getta che verranno appena 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 & Quot; Oh, questo è il tipo Foo! So come dovrebbe apparire in JSON. & Quot;
Detto questo, potresti provare JSON.Net per eseguire la serializzazione. Non ho idea se funzionerà
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
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 su " oggetto "
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);
}
}
}