Jak serializować typ anonimowy C # do ciągu JSON?

162

Próbuję użyć następującego kodu do serializacji typu anonimowego do JSON:

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

Jednak pojawia się następujący wyjątek, gdy jest to wykonywane:

Nie można serializować typu „<> f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]”. Rozważ oznaczenie go atrybutem DataContractAttribute i oznaczenie wszystkich jego elementów członkowskich, które chcesz serializować, za pomocą atrybutu DataMemberAttribute. Zobacz dokumentację Microsoft .NET Framework dla innych obsługiwanych typów.

Nie mogę zastosować atrybutów do typu anonimowego (o ile wiem). Czy jest inny sposób wykonania tej serializacji, czy czegoś mi brakuje?

JC Grubbs
źródło

Odpowiedzi:

159

Wypróbuj JavaScriptSerializer zamiast DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);
Nick Berardi
źródło
17
Trackback, wygląda na to, że został wycofany z wersji SP1.
Biswanath
7
w przypadku czegoś tak przestarzałego, wydaje się, że jest używany w wielu nowych frameworkach firmy Microsoft, w tym w MVC. aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi,
1
Jak dołączyć ten projekt, m.in. non-asp.net (aplikacja konsolowa)?
Alxandr
4
@Alxandr: Musisz odwołać się System.Web.Extensions.dlli dodać using System.Web.Script.Serialization;oświadczenie.
randomguy
1
@randomgui problem polegał na tym, że typ wyjścia projektu został ustawiony na profil klienta.
Alxandr
75

Jak wspominali inni, Newtonsoft JSON.NET jest dobrą opcją. Oto konkretny przykład prostej serializacji JSON:

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

Uważam, że jest to bardzo elastyczna, wszechstronna biblioteka.

Matthew Nichols
źródło
14

Możesz wypróbować mój ServiceStack JsonSerializer, który jest obecnie najszybszym serializatorem .NET JSON . Obsługuje serializację DataContract, dowolny typ POCO, interfejsy, obiekty z późnym wiązaniem, w tym typy anonimowe itp.

Podstawowy przykład

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

Uwaga: używaj tylko Microsofts JavaScriptSerializer, jeśli wydajność nie jest dla ciebie ważna, ponieważ musiałem pominąć ją w moich testach porównawczych, ponieważ jest do 40x-100x wolniejsza niż inne serializatory JSON.

mit
źródło
7
Używam MS JavaScriptSerializer na stosie MVC3 do serializacji obiektów z niewielkimi ilościami danych. W takich przypadkach jest to dość szybkie, a zrobienie tego, czego potrzebuję, zajmuje mniej niż milisekundę. Samo zapytanie DB zajmuje 50x-100x dłużej, więc nie jest to tak naprawdę znaczące wąskie gardło w mojej sytuacji.
Brian
2
Przedwczesna optymalizacja to ... No wiesz.
Mathias Lykkegaard Lorenzen
1
Łącze „najszybszy serializator .NET JSON” to 404ing! Dodatkowo ta odpowiedź ma ponad 5 i pół roku. Czy masz aktualne informacje na temat wydajności różnych serializatorów .NET JSON?
ErikE
11

Proszę zauważyć, że pochodzi z 2008 roku. Dzisiaj argumentowałbym, że serializator powinien być wbudowany i prawdopodobnie można użyć atrybutów swagger +, aby poinformować konsumentów o punkcie końcowym i zwracanych danych.


Twierdzę, że nie powinieneś serializować anonimowego typu . Znam pokusę tutaj; chcesz szybko wygenerować kilka typów do odrzucenia, które będą używane w luźnym środowisku, znanym jako JavaScript w przeglądarce. Mimo to stworzyłbym rzeczywisty typ i udekorowałbym go jako serializowalny. Następnie możesz zdecydowanie wpisać swoje metody internetowe. Chociaż nie ma to znaczenia dla Javascript, dodaje trochę dokumentacji własnej do metody. Każdy rozsądnie doświadczony programista będzie mógł spojrzeć na sygnaturę funkcji i powiedzieć: „O, to jest typ Foo! Wiem, jak to powinno wyglądać w JSON”.

Powiedziawszy to, możesz wypróbować JSON.Net do wykonania serializacji. Nie mam pojęcia, czy to zadziała

Jason Jackson
źródło
3
JSON.Net działa dobrze. Twierdzę, że nie powinieneś :), myślę, że w wielu przypadkach jest to całkiem uzasadnione.
kwiecieńchild
2
Po obejrzeniu typów „do odrzucenia” używanych w MVC widzę kilka fascynujących zastosowań. Myślę, że jest to bardzo przydatne narzędzie w skrzynce narzędziowej .Net.
Matthew Whited
12
Jest to kwestia, w której również złagodziłem, szczególnie w przypadku typów tylko konsumpcyjnych. Ale jeśli obiekt wraca na serwer lub jest używany w więcej niż jednej lokalizacji, nadal uważam, że utworzenie typu spowoduje mniej problemów.
Jason Jackson,
Deserializacja w stylu DataContract nie obsługuje dobrze typów polimorficznych. Musisz napisać swój własny desserializer. Zbyt duża konserwacja kodu.
micahhoover
Przykładem użycia, w którym serializacja typów anonimowych jest przydatna, są testy jednostkowe dla internetowych interfejsów API.
howcheng
9

Najszybszy sposób, jaki znalazłem, był następujący:

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

Przestrzeń nazw: System.Web.Script.Serialization.JavaScriptSerializer

i31nGo
źródło
2
A do deserializacji:. . dynamiczny myObject = JsonConvert.DeserializeObject <dynamic> (wyjście); . . odniesienie: Newtonsoft.json.dll
i31nGo,
2

Możesz użyć Newtonsoft.Json.

var warningJSON = JsonConvert.SerializeObject(new {
                warningMessage = "You have been warned..."
            });
Ahmet Arslan
źródło
1

Zakładając, że używasz tego dla usługi internetowej, możesz po prostu zastosować następujący atrybut do klasy:

[System.Web.Script.Services.ScriptService]

Następnie następujący atrybut do każdej metody, która powinna zwrócić Json:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

I ustaw typ zwracania metod na „obiekt”

Paweł
źródło
W przypadku standardowej usługi sieciowej ASP [ScriptMethod (ResponseFormat = ResponseFormat.Json)] nie jest wymagana w metodzie, wystarczy [WebMethod]. Nie należy również ustawiać zwracanego typu na obiekt, może i powinien być on silnie wpisany jako typ niezłożony (tj. Można go serializować).
wiersz 1
-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
źródło
To nie powoduje serializacji anonimowych typów zgodnie z pytaniem
Mark Sowul