So entfernen Sie k__BackingField aus json beim Deserialisieren

103

Ich erhalte das k_BackingField in meinem zurückgegebenen JSON, nachdem ich eine XML-Datei in ein .net c # -Objekt serialisiert habe.

Ich habe das DataContract- und das DataMember-Attribut zum .net c # -Objekt hinzugefügt, aber dann erhalte ich auf der json-Client-Seite nichts.

[XmlRoot("person")]
[Serializable]
public class LinkedIn
{
    [XmlElement("id")]
    public string ID { get; set; }

    [XmlElement("industry")]
    public string Industry { get; set; }

    [XmlElement("first-name")]
    public string FirstName { get; set; }

    [XmlElement("last-name")]
    public string LastName { get; set; }
    [XmlElement("headline")]
}

Beispiel für den zurückgegebenen json:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"
Den Stapel zu füllen ist das, was ich tue
quelle

Antworten:

45

Die automatische Eigenschaftssyntax wird eigentlich nicht empfohlen, wenn die Klasse bei der Serialisierung verwendet werden kann. Grund dafür ist, dass das Hintergrundfeld vom Compiler generiert wird, der bei jeder Kompilierung des Codes unterschiedlich sein kann. Dies kann zu Inkompatibilitätsproblemen führen, selbst wenn keine Änderungen an der Klasse vorgenommen werden (nur das erneute Kompilieren des Codes).

Ich denke, das Anwenden des DataMember-Attributs wird das Problem in diesem Fall beheben. Ich würde jedoch empfehlen, die vollständige Eigenschaftssyntax zu verwenden, wenn die Klasse bei der Serialisierung verwendet werden muss.

Zacken
quelle
Lol, hat die Langversion implementiert und die privaten Felder auf client.home gesetzt: Object _fName: "Storefront" _headline: "CEO at StorefrontDoors.NET" _id: "_industry:" "
Den Stapel
21
Hinzufügen dieses Datenvertrags zum Anfang der Klasse und Datenelement zu jeder Eigenschaft, an der ich interessiert bin.
Den Stapel zu füllen ist das, was ich
3
@ AlumCloud.Com +1 für [DataContract] und [DataMember]. Vergessen Sie nicht hinzuzufügen: System.Runtime.Serialization
Ian Newland
109

[Serializable]Aus deiner Klasse entfernen

Safaa Elgendi
quelle
2
Jetzt frage ich mich, warum ich dachte, ich brauche [Serializable] überhaupt. Meine XML-Serialisierung funktioniert ohne und JSON funktioniert ohne.
Rhyous
11
Dies funktioniert nicht mit WCF Services. Wenn Sie eine Nutzlast mit RESTful-Diensten zurückgeben, werden keine Daten ausgegeben, wenn Sie [Serializable] entfernen. Fügen Sie System.Runtime.Serialization hinzu und verwenden Sie [DataContract] für die Klasse, [DataMember] für Eigenschaften.
Ian Newland
Diese Antwort UND Ian Kommentar scheint beide Fälle abzudecken. Für WCF oder nicht für WCF ist das die Frage.
GranadaCoder
1
@Rhyous - In der Web-API benötigen Sie [Serializable] nicht, da die Web-API mit der Annahme eingerichtet ist, dass Sie Ihre Objekte serialisieren und zurückgeben (da dies im Grunde die gesamte Idee ist) - in anderen C # -Anwendungen, die Sie im Allgemeinen verwenden brauchen serialisierbar, um serialisierbare Objekte zu unterscheiden
Jon Story
Vielen Dank, ich war festgefahren [Serializable], daher hat das Hinzufügen von Hintergrundfeldern geholfen.
Ohmusama
58

Der Standard-WebApi-Serializer fügt die Syntax "__BackingField:" zu den automatischen Eigenschaften von c # hinzu. Fügen Sie dies Ihrer WebConfig in App_Start hinzu, um den saubereren JSON zu erhalten, nach dem Sie möglicherweise suchen.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Dan
quelle
3
Dies hat das Problem behoben. Ich denke, Auto-Eigenschaften sind sauber. Die Verwendung von Hintergrundfeldern überall scheint dumm zu sein. und führt viel Unordnung und manchmal Verwirrung.
Romesh D. Niriella
Das hat bei mir funktioniert. In meinem Fall hatte ich eine vorhandene Klasse, die bereits von WCF- und ASMX-Webservices verwendet wurde, sodass ich sie nicht nur für mein neues WebAPI-Projekt ändern konnte.
Samiup
4
Die Frage ist, warum der WebApi-Serializer standardmäßig "__BackingField:" hinzufügt.
Teoman Shipahi
gute Lösung. In meinem Fall muss ich [Serializable] verwenden, um in Memcache zu speichern. Serialisierbar ist erforderlich.
Bình Nguyễn Quang
2
Was würde ich ohne StackOverflow tun? Vielen Dank.
Camainc
35

Wir haben einige Objekte, die als gekennzeichnet sind, [Serializable]damit sie mit herkömmlichen Methoden serialisiert werden können, die wir jedoch für die Verwendung mit der Web-API in JSON sauber serialisieren müssen. Einstellung IgnoreSerializableAttributeauftrue wird verhindert, dass sich Newtonsoft.Json wie die Serialisierer von Microsoft verhält, und stattdessen werden nur die öffentlichen Eigenschaften serialisiert.

TLDR: Fügen Sie dies zu WebApiConfig.cs hinzu:

((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;

Moderator: Anstatt eine wirklich gute Antwort auf eine mehrmals gestellte Frage zu löschen, löschen Sie bitte die doppelte Frage. Dies ist eine gültige Antwort auf eine gültige Frage.

Richard
quelle
3
Dies sollte die richtige Antwort sein. Das Entfernen der Serialisierung oder die Verwendung von Datenvertrags- und Datenelementattributen ist nicht immer die richtige Lösung.
Houssam Hamdan
Viele von uns, einschließlich OP, verwenden nicht Webapi oder MVVM oder was auch immer ihr gerade tut. Was ist app_start und webapiconfig, wenn ich einen normalen Seifen-WCF-Dienst mit service.svc habe?
Christian
10

Einfach Einfach und anständig, um Daten verfügbar zu machen Wir müssen Daten im Objekt einem leicht lesbaren und konsistenten Format aussetzen


Entfernen Sie zuerst [Serializable]

    [Serializable]

Fügen Sie nun [DataContract] in der Klasse und [DataMember] für die Eigenschaft wie im folgenden Beispiel hinzu

[DataContract]
public class UserDiscretion : UserReport
{
    [DataMember]
    public String DiscretionCode { get; set; }
    public String DiscretionDescription { get; set; }
}

Hoffe diese Hilfe
Danke.

Nagendra Upwanshi
quelle
1
Wenn Sie die Web-API verwenden, müssen Sie die Attribute DataContract und DataMember überhaupt nicht hinzufügen. Geben Sie einfach das Objekt zurück, und es wird automatisch serialisiert.
Jon Story
Wenn jemand mit der Entwicklung von Grund auf neu beginnt, ist es großartig, die Web-API zu verwenden, die den Objektrückgabetyp bereitstellt. Für die Bereitstellung für den Client ist keine Art von Typumwandlung erforderlich. Wenn Sie sich jedoch in der vorhandenen Anwendung in der vorhandenen Anwendung befinden, müssen Sie zunächst [Serializable] entfernen und dann [DataContract] in der Klasse und [DataMember] für die unten angegebene Eigenschaft hinzufügen
Nagendra Upwanshi,
1
Dies fügt Ihren Klassen eine enorme Menge an "Lärm" hinzu und ist im Wesentlichen unnötig (siehe alle anderen Kommentare). Wenn Sie jedoch das Bedürfnis haben, dies tatsächlich zu tun, würde ich empfehlen, PostSharp zu verwenden, um den Code während der Kompilierung für Sie hinzuzufügen, damit Ihre Klassen nicht mit all diesen Attributen überfüllt sind.
Camainc
7

Einige Optionen:

  1. [Serializable]Vom Modell entfernen

  2. Fügen Sie [DataContract]und [DataMember]zu Ihrem Modell zusammen mit [Serializable]

  3. Fügen Sie die folgende Zeile hinzu App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Jayaprakash Muthugopal
quelle
3

Eine weitere Lösung, die bei JSON.NET hilfreich sein kann. Es kann ausreichen, die Klasse mit dem Attribut [Newtonsoft.Json.JsonObject] zu markieren.

Ich habe mit cs-Klassen gearbeitet, die aus xsd erstellt wurden, und einige Eigenschaften mithilfe von Teilklassen hinzugefügt. Nach der JSON-Serialisierung wurden diese Eigenschaften mit k_BackingField markiert. Die in anderen Antworten erwähnten JsonFormatter-Einstellungen halfen ebenfalls, aber einfacher war es, eine Teilklasse mit dem Attribut [JsonObject] zu markieren.

sarh
quelle
2

Ich habe DataContractJsonSerializermit einer Klasse aus einer anderen Assembly verwendet, die das SerializableAttribut hatte. Die Ausgabe enthielt "k__BackingField". Durch Entfernen des SerializableAttributs (in der anderen Assembly) wurde dies behoben. Nicht sicher warum.

Kleiner Endian
quelle
0

Angenommen, Sie sehen dieses Problem in Ihrem MVC-Projekt, dann ist es ziemlich einfach, die Verwendung von @ Html.JsonData zu ersetzen. Hier ist ein Codeausschnitt, der in der Vergangenheit für mich funktioniert hat:

<input type="hidden" id="Model" value="@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model))" />

Nicht so elegant, aber zur Not einfach.

Ryan Roark
quelle
0

Ich hatte dieses Problem, wenn ich Selbstreferenzeigenschaften in meiner Klasse habe, wie z.

class Person {
 List<Person> Friends { get; set;}
}

Und es gab ein Ergebnis, die Person war mit sich selbst befreundet. Ich habe nur sichergestellt, dass meine Ergebnismenge keine selbstreferenzierenden Objekte enthält. Hoffe das hilft.

Teoman Shipahi
quelle
0

Ich musste die Attribute [Serializable] verwenden, daher war das Entfernen keine Option.

XmlSerializer ignoriert [XmlAttribute] in WebApi

Die obige Lösung hat es für mich gelöst.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
quelle
0

In meinem Fall war dieser Fehler für die Newtonsoft.Json-Version, der Server suchte nach der Version 6.0.0 und ich hatte die Version 11.0, also musste ich die Version 6.0.0 installieren

Andres Guillen
quelle
-2

Freunde, deklarieren Sie keine Eigenschaften wie diese:

public String DiscretionCode { get; set; }
public String DiscretionDescription { get; set; }

Aber erstellen Sie zusätzliche Vars, wie alte ...

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}
Humberto Gonçalves de Almeida
quelle
1
Warum? Könnten Sie eine Resonanz geben?
Lucenty
@Lucenty gibt es einen JSON wie diesen .. [{"discreationCode": "x"}], wenn serialisiert.
Ammar Ameerdeen
Aber das würde ich erwarten - so serialisiert JSON Daten. Und ich denke, dass der Code mit Auxiliar-Vars das gleiche Ergebnis liefert.
Lucenty
k_BackingField wurde hinzugefügt, um anzuzeigen, dass eine Auto-Eigenschaft serialisiert wurde. Wenn Sie die Auto-Eigenschaft in eine Eigenschaft und ein Hintergrundfeld umgestalten, wird das Problem behoben. Ich denke, es gibt bessere Lösungen in diesem Thread, aber das funktioniert.
timB33