Comment supprimer k__BackingField de json lors de la désérialisation

104

J'obtiens le k_BackingField dans mon json renvoyé après avoir sérialisé un fichier xml vers un objet .net c #.

J'ai ajouté le DataContract et l'attribut DataMember à l'objet .net c # mais je n'obtiens rien du côté client json.

[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")]
}

Exemple du json renvoyé:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"
Remplir la pile, c'est ce que je fais
la source

Réponses:

45

La syntaxe de propriété automatique n'est en fait pas recommandée si la classe peut être utilisée dans la sérialisation. La raison étant que le champ de sauvegarde est généré par le compilateur qui peut être différent à chaque fois que le code temporel est compilé. Cela peut entraîner des problèmes d'incompatibilité même si aucune modification n'est apportée à la classe (recompilation du code).

Je pense que l'application de l'attribut DataMember résoudra le problème dans ce cas. Mais je recommanderais d'utiliser la syntaxe de propriété complète, si la classe doit être utilisée dans la sérialisation.

déchiquetés
la source
Lol, a implémenté la version longue et a défini les champs privés sur client.home: Objet _fName: "Storefront" _headline: "PDG de StorefrontDoors.NET" _id: "" _industry: ""
Remplir la pile est ce que je fais
21
l'ajout de ce contrat de données en haut de la classe et du datamember à chaque propriété qui m'intéresse a fonctionné.
Remplir la pile, c'est ce que je fais
3
@ AlumCloud.Com +1 pour [DataContract] et [DataMember]. N'oubliez pas d'ajouter: System.Runtime.Serialization
Ian Newland
109

Retirer [Serializable]de votre classe

Safaa Elgendi
la source
2
Maintenant, je me demande pourquoi je pensais avoir besoin de [Serializable] en premier lieu. Ma sérialisation Xml fonctionne sans et JSON fonctionne sans elle.
Rhyous
11
Cela ne fonctionne pas avec les services WCF. Lors du retour d'une charge utile à l'aide des services RESTful, cela ne donne aucune donnée si vous supprimez [Serializable]. Ajoutez System.Runtime.Serialization et utilisez [DataContract] pour la classe, [DataMember] pour les propriétés.
Ian Newland
Cette réponse ET le commentaire de Ian semblent couvrir les deux cas. À WCF ou pas à WCF, telle est la question.
granadaCoder
1
@Rhyous - dans l'API Web, vous n'avez pas besoin de [Serializable], car l'API Web est configurée avec l'hypothèse que vous allez sérialiser et renvoyer vos objets (puisque c'est essentiellement l'idée entière) - dans d'autres applications C #, vous besoin de sérialisable pour différencier les objets sérialisables
Jon Story
Merci, j'étais coincé [Serializable], donc l'ajout de champs de sauvegarde a aidé.
ohmusama
59

Le sérialiseur WebApi par défaut ajoutera cette syntaxe «__BackingField:» aux propriétés automatiques c #. Ajoutez ceci à votre WebConfig dans App_Start pour obtenir le json plus propre que vous recherchez.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Dan
la source
3
Cela a résolu le problème. Je pense que les propriétés automobiles sont propres. Utiliser des champs de support partout semble stupide. et introduit beaucoup de désordre et parfois de confusion.
Romesh D.Niriella
Cela a fonctionné pour moi. Dans mon cas, j'avais une classe existante qui était déjà utilisée par les services Web WCF et ASMX, donc je ne pouvais pas simplement la changer pour mon nouveau projet WebAPI.
samiup
4
La question est pourquoi diable le sérialiseur WebApi ajoutera que "__BackingField:" par défaut?
Teoman shipahi
bonne solution. dans mon cas, je dois utiliser [Serializable] save dans memcache. Sérialisable est obligatoire.
Bình Nguyễn Quang
2
Que ferais-je sans StackOverflow? Merci.
camainc
35

Nous avons certains objets qui sont marqués comme [Serializable]afin qu'ils puissent être sérialisés à l'aide de méthodes traditionnelles, mais que nous devons avoir sérialisé proprement en JSON pour une utilisation avec l'API Web. Définir IgnoreSerializableAttributesur trueempêchera Newtonsoft.Json de se comporter comme les serialiseurs de Microsoft et à la place, il sérialisera simplement les propriétés publiques.

TLDR: ajoutez ceci à WebApiConfig.cs:

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

Modérateur: Plutôt que de supprimer une très bonne réponse à une question qui a été posée plusieurs fois, veuillez supprimer la question en double. Ceci est une réponse valide à une question valide.

Richard
la source
3
Cela devrait être la bonne réponse. La suppression de la sérialisation ou l'utilisation d'attributs de contrat de données et de membre de données n'est pas toujours la bonne solution.
Houssam Hamdan
Beaucoup d'entre nous, y compris OP, n'utilisent pas Webapi ou MVVM ou quoi que ce soit dont vous parlez. Qu'est-ce que app_start et webapiconfig lorsque j'ai un service soap WCF normal avec service.svc?
Christian
10

Simple moyen facile et décent d'exposer les données Nous devons exposer les données dans l'objet dans un format facile à lire et cohérent


Supprimez d'abord [Serializable]

    [Serializable]

ajoutez maintenant [DataContract] dans la classe et [DataMember] pour la propriété comme dans l'exemple ci-dessous

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

J'espère que cette aide
Merci.

Nagendra Upwanshi
la source
1
Si vous utilisez l'API Web, il n'est pas du tout nécessaire d'ajouter les attributs DataContract et DataMember - renvoyez simplement l'objet et il sera sérialisé automatiquement.
Jon Story
Si quelqu'un commence le développement à partir de zéro, il sera donc bon d'utiliser l'API Web qui fournira le type de retour d'objet ne nécessitera aucun type de conversion de type pour l'exposition au client. Mais pour la question @ AlumCloud.com, s'il est dans l'application existante, la solution à son problème sera d'abord supprimer [Serializable] puis ajouter [DataContract] dans la classe et [DataMember] pour la propriété comme ci-dessous comme suggéré
Nagendra Upwanshi
1
Cela ajoute énormément de «bruit» à vos cours et est essentiellement inutile (voir tous les autres commentaires). Si vous ressentez le besoin de le faire, cependant, je recommanderais d'utiliser quelque chose comme PostSharp pour ajouter le code pour vous lors de la compilation afin qu'il n'encombre pas vos classes avec tous ces attributs.
camainc
7

Deux options:

  1. Supprimer [Serializable]du modèle

  2. Ajoutez [DataContract]et [DataMember]à votre modèle avec [Serializable]

  3. Ajouter ci-dessous la ligne à App_Start/WebApiConfig.cs

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

Une autre solution qui peut aider dans le cas de JSON.NET. Il peut suffire de marquer la classe avec l'attribut [Newtonsoft.Json.JsonObject].

Je travaillais avec des classes cs construites à partir de xsd et ajoutais des propriétés en utilisant des classes partielles. Après la sérialisation json, ces propriétés ont été marquées avec k_BackingField. Les paramètres JsonFormatter mentionnés dans d'autres réponses ont également aidé, mais le plus simple était de marquer une classe partielle avec l'attribut [JsonObject].

sarh
la source
2

J'utilisais DataContractJsonSerializeravec une classe d'un autre assemblage qui avait l' Serializableattribut. La sortie contenait "k__BackingField". La suppression de l' Serializableattribut (dans l'autre assembly) a résolu ce problème. Pas certain de pourquoi.

Petit endian
la source
0

En supposant que vous voyiez ce problème dans votre projet MVC, j'ai trouvé qu'il était assez simple de remplacer l'utilisation de @ Html.JsonData. Voici un extrait de code qui a fonctionné pour moi dans le passé:

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

Pas aussi élégant, mais simple à la rigueur.

Ryan Roark
la source
0

J'ai eu ce problème lorsque j'ai des propriétés d'auto-référence dans ma classe telles que;

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

Et il y avait un résultat, la personne était amie avec elle-même. Je me suis juste assuré qu'il n'y avait pas d'objets auto-référençables dans mon jeu de résultats. J'espère que cela t'aides.

Shipahi Teoman
la source
0

J'ai dû utiliser les attributs [Serializable], donc le supprimer n'était pas une option.

XmlSerializer ignore [XmlAttribute] dans WebApi

La résolution ci-dessus l'a résolu pour moi.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
la source
0

dans mon cas, cette erreur concernait la version Newtonsoft.Json, le serveur recherchait la version 6.0.0 et j'avais la 11.0, j'ai donc dû installer la version 6.0.0

Andres Guillen
la source
-2

Amis, ne déclarez pas de propriétés comme celle-ci:

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

Mais, créez des vars auxiliaires, comme les anciens ...

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}
Humberto Gonçalves de Almeida
la source
1
Pourquoi? Pouvez-vous donner une réponse?
Lucenty
@Lucenty cela donne un JSON comme celui-ci .. [{"discreationCode": "x"}], lors de la sérialisation.
Ammar Ameerdeen
Mais c'est ce à quoi je m'attendrais - c'est ainsi que JSON sérialise les données. Et je pense que le code avec les variables auxiliaires donnera le même résultat.
Lucenty
k_BackingField a été ajouté pour indiquer qu'une propriété automatique a été sérialisée. Si vous refactorisez la propriété automatique en une propriété et un champ de sauvegarde, le problème disparaîtrait. Je pense qu'il y a de meilleures solutions dans ce fil, mais cela fonctionne.
timB33