Wie serialisiere ich einen anonymen C # -Typ in eine JSON-Zeichenfolge?

161

Ich versuche, den folgenden Code zu verwenden, um einen anonymen Typ für JSON zu serialisieren:

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

Ich erhalte jedoch die folgende Ausnahme, wenn dies ausgeführt wird:

Typ '<> f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]' kann nicht serialisiert werden. Markieren Sie es mit dem DataContractAttribute-Attribut und markieren Sie alle Mitglieder, die Sie serialisieren möchten, mit dem DataMemberAttribute-Attribut. Weitere unterstützte Typen finden Sie in der Microsoft .NET Framework-Dokumentation.

Ich kann keine Attribute auf einen anonymen Typ anwenden (soweit ich weiß). Gibt es eine andere Möglichkeit, diese Serialisierung durchzuführen, oder fehlt mir etwas?

JC Grubbs
quelle

Antworten:

159

Probieren Sie den JavaScriptSerializer anstelle des DataContractJsonSerializer aus

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);
Nick Berardi
quelle
17
Trackback, es scheint, dass es in SP1 veraltet war.
Biswanath
7
Für etwas so Veraltetes scheint es in vielen neuen Microsoft-Frameworks, einschließlich MVC, verwendet zu werden. aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi
1
Wie füge ich dieses ua non-asp.net-Projekt (Konsolenanwendung) hinzu?
Alxandr
4
@Alxandr: Sie müssten System.Web.Extensions.dlleine using System.Web.Script.Serialization;Anweisung referenzieren und hinzufügen .
Randomguy
1
@ randomgui Problem war Projektausgabetyp wurde auf Client-Profil gesetzt.
Alxandr
75

Wie bereits erwähnt, ist Newtonsoft JSON.NET eine gute Option. Hier ist ein spezielles Beispiel für eine einfache JSON-Serialisierung:

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

Ich habe festgestellt, dass es sich um eine sehr flexible und vielseitige Bibliothek handelt.

Matthew Nichols
quelle
14

Sie können meinen ServiceStack JsonSerializer ausprobieren, der derzeit der schnellste .NET JSON-Serializer ist . Es unterstützt die Serialisierung von DataContracts, beliebigen POCO-Typen, Schnittstellen, spät gebundenen Objekten, einschließlich anonymer Typen usw.

Grundlegendes Beispiel

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

Hinweis: Verwenden Sie Microsoft JavaScriptSerializer nur, wenn die Leistung für Sie nicht wichtig ist, da ich sie aus meinen Benchmarks herausnehmen musste, da sie bis zu 40x-100x langsamer ist als die anderen JSON-Serializer.

Mythos
quelle
7
Ich verwende den MS JavaScriptSerializer auf dem MVC3-Stapel, um Objekte mit kleinen Datenmengen zu serialisieren. In diesen Fällen ist es ziemlich schnell und dauert weniger als eine Millisekunde, um das zu tun, was ich brauche. Die DB-Abfrage selbst dauert 50x-100x länger, daher ist dies in meiner Situation kein wesentlicher Engpass.
Brian
2
Vorzeitige Optimierung ist ein ... Nun, Sie wissen.
Mathias Lykkegaard Lorenzen
1
Der Link "Schnellster .NET JSON-Serializer" ist 404ing! Außerdem ist diese Antwort über 5 1/2 Jahre alt. Haben Sie ein Update zur Leistung verschiedener .NET JSON-Serialisierer?
ErikE
11

Bitte beachten Sie, dass dies aus dem Jahr 2008 stammt. Heute würde ich argumentieren, dass der Serializer eingebaut sein sollte und dass Sie wahrscheinlich Swagger + -Attribute verwenden können, um Verbraucher über Ihren Endpunkt zu informieren und Daten zurückzugeben.


Ich würde argumentieren, dass Sie keinen anonymen Typ serialisieren sollten . Ich kenne die Versuchung hier; Sie möchten schnell einige Wegwerftypen generieren, die nur in einer Umgebung mit losem Typ, auch bekannt als Javascript, im Browser verwendet werden. Trotzdem würde ich einen tatsächlichen Typ erstellen und ihn als serialisierbar dekorieren. Dann können Sie Ihre Webmethoden stark eingeben. Während dies für Javascript kein Jota ausmacht, fügt es der Methode eine Selbstdokumentation hinzu. Jeder einigermaßen erfahrene Programmierer kann sich die Funktionssignatur ansehen und sagen: "Oh, das ist Typ Foo! Ich weiß, wie das in JSON aussehen sollte."

Sie können jedoch JSON.Net ausprobieren , um die Serialisierung durchzuführen . Ich habe keine Ahnung, ob es funktionieren wird

Jason Jackson
quelle
3
JSON.Net funktioniert einwandfrei. Ich würde argumentieren, dass Sie nicht sollten :), ich denke, es ist in vielen Fällen ziemlich legitim.
Aprilkind
2
Nachdem ich die in MVC verwendeten "Wegwerf" -Typen gesehen habe, kann ich einige überzeugende Verwendungen erkennen. Ich denke, es ist ein sehr praktisches Werkzeug, das Sie in Ihrer .Net-Toolbox haben sollten.
Matthew Whited
12
Dies ist ein Punkt, auf den ich auch eingegangen bin, insbesondere bei Typen, die nur für den Verbrauch bestimmt sind. Wenn das Objekt jedoch eine Rückreise zum Server unternimmt oder an mehr als einem Ort verwendet wird, glaube ich immer noch, dass das Erstellen eines Typs zu weniger Problemen führt.
Jason Jackson
Die De-Serialisierung im DataContract-Stil kann mit polymorphen Typen nicht gut umgehen. Sie müssen Ihren eigenen De-Serializer schreiben. Zu viel Codepflege.
Micahhoover
Ein Anwendungsfall, bei dem das Serialisieren anonymer Typen nützlich ist, sind Komponententests für Web-APIs.
Howcheng
9

Der schnellste Weg, den ich gefunden habe, war folgender:

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

Namespace: System.Web.Script.Serialization.JavaScriptSerializer

i31nGo
quelle
2
Und zur Deserialisierung :. . dynamisches myObject = JsonConvert.DeserializeObject <dynamisch> (Ausgabe); . . Referenz: Newtonsoft.json.dll
i31nGo
2

Sie könnten Newtonsoft.Json verwenden.

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

Angenommen, Sie verwenden dies für einen Webdienst, können Sie einfach das folgende Attribut auf die Klasse anwenden:

[System.Web.Script.Services.ScriptService]

Dann das folgende Attribut für jede Methode, die Json zurückgeben soll:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

Und setzen Sie den Rückgabetyp für die Methoden auf "Objekt".

Paul
quelle
Für einen Standard-ASP-Webdienst wird [ScriptMethod (ResponseFormat = ResponseFormat.Json)] für die Methode nicht benötigt, [WebMethod] reicht aus. Außerdem sollten Sie den Rückgabetyp nicht auf Objekt setzen, er kann und sollte stark mit einem nicht komplexen Typ (dh kann serialisiert werden) typisiert werden.
Reihe1
-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
quelle
Dies serialisiert keine anonymen Typen gemäß der Frage
Mark Sowul