Come rimuovere k__BackingField da json quando Deserialize


104

Ricevo il k_BackingField nel mio json restituito dopo aver serializzato un file xml in un oggetto .net c #.

Ho aggiunto DataContract e l'attributo DataMember all'oggetto .net c # ma poi non ottengo nulla su json, lato client.

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

Esempio del json restituito:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"

Risposte:


45

La sintassi della proprietà automatica in realtà non è consigliata se la classe può essere utilizzata nella serializzazione. Il motivo è che il campo di supporto è generato dal compilatore che può essere diverso ogni volta che viene compilato il codice temporale. Ciò può causare problemi di incompatibilità anche se non viene apportata alcuna modifica alla classe (basta ricompilare il codice).

Penso che l'applicazione dell'attributo DataMember risolverà il problema in questo caso. Ma consiglierei di utilizzare la sintassi completa delle proprietà, se la classe deve essere utilizzata nella serializzazione.


Lol, ha implementato la versione lunga e ha impostato i campi privati ​​su client.home: Object _fName: "Storefront" _headline: "CEO at StorefrontDoors.NET" _id: "" _industry: ""
Filling The Stack is What I DO

21
aggiungendo quel datacontract all'inizio della classe e datamember a ogni proprietà che mi interessa ha lavorato.
Riempire lo stack è quello che faccio il

3
@ AlumCloud.Com +1 per [DataContract] e [DataMember]. Non dimenticare di aggiungere: System.Runtime.Serialization
Ian Newland

109

Rimuovi [Serializable]dalla tua classe


2
Ora mi chiedo perché ho pensato di aver bisogno di [Serializable] in primo luogo. La mia serializzazione Xml funziona senza e JSON funziona senza di essa.
Rhyous

11
Questo non funziona con i servizi WCF. Quando si restituisce un payload utilizzando i servizi RESTful, questo non produce alcun dato se si rimuove [Serializable]. Aggiungere System.Runtime.Serialization e utilizzare [DataContract] per la classe, [DataMember] per le proprietà.
Ian Newland

Questa risposta e il commento di Ian sembrano coprire entrambi i casi. Per WCF o non per WCF, questo è il problema.
granadaCoder

1
@Rhyous - nell'API Web non hai bisogno di [Serializable], perché l'API Web è configurata con il presupposto che stai per serializzare e restituire i tuoi oggetti (poiché questa è fondamentalmente l'intera idea) - in altre applicazioni C # generalmente serve Serializable per differenziare gli oggetti serializzabili
Jon Story

Grazie, sono rimasto bloccato [Serializable], quindi l'aggiunta di campi di supporto ha aiutato.
ohmusama

59

Il serializzatore WebApi predefinito aggiungerà quella sintassi "__BackingField:" alle proprietà auto c #. Aggiungilo al tuo WebConfig in App_Start per ottenere il json dall'aspetto più pulito che potresti cercare.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

3
Questo ha risolto il problema. Penso che le proprietà dell'auto siano pulite. Usare campi di supporto ovunque sembra stupido. e introduce molta confusione e talvolta confusione.
Romesh D. Niriella

Questo ha funzionato per me. Nel mio caso, avevo una classe esistente che era già utilizzata dai servizi web WCF e ASMX, quindi non potevo semplicemente cambiarla per il mio nuovo progetto WebAPI.
samiup

4
La domanda è: perché mai il serializzatore WebApi aggiungerà "__BackingField:" per impostazione predefinita?
Teoman shipahi

buona soluzione. nel mio caso, devo usare il salvataggio [Serializable] in memcache. Serializzabile è necessario.
Bình Nguyễn Quang

2
Cosa farei senza StackOverflow? Grazie.
camainc

35

Abbiamo alcuni oggetti contrassegnati come in [Serializable]modo che possano essere serializzati utilizzando metodi tradizionali, ma che è necessario serializzare in modo pulito in JSON per l'utilizzo con l'API Web. L'impostazione IgnoreSerializableAttributesu trueimpedirà a Newtonsoft.Json di comportarsi come i serializzatori di Microsoft e invece serializzerà solo le proprietà pubbliche.

TLDR: aggiungi questo a WebApiConfig.cs:

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

Moderatore: invece di eliminare una risposta davvero valida a una domanda che è stata posta più volte, elimina la domanda duplicata. Questa è una risposta valida a una domanda valida.


3
Questa dovrebbe essere la risposta giusta. La rimozione della serializzazione o l'utilizzo degli attributi datacontract e datamember non è sempre la soluzione corretta.
Houssam Hamdan

Molti di noi, incluso OP, non usano Webapi o MVVM o qualsiasi cosa di cui vi occupiate. Cosa sono app_start e webapiconfig quando ho un normale servizio soap WCF con service.svc?
Christian

10

Semplice Modo semplice e decente per esporre i dati Abbiamo bisogno di esporre i dati in un oggetto in un formato facilmente leggibile e coerente


Prima rimuovi [Serializable]

    [Serializable]

ora aggiungi [DataContract] nella classe e [DataMember] per la proprietà come nell'esempio seguente

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

Spero che questo aiuto
Grazie.


1
Se si utilizza l'API Web, non è necessario aggiungere affatto gli attributi DataContract e DataMember: è sufficiente restituire l'oggetto e verrà serializzato automaticamente.
Jon Story,

Se qualcuno inizia lo sviluppo da zero, sarà fantastico usare l'API Web che fornirà il tipo restituito dall'oggetto non richiederà alcun tipo di casting del tipo per l'esposizione al client. Ma per la domanda su @ AlumCloud.com, se si trova nell'applicazione esistente, la soluzione per il suo problema sarà innanzitutto rimuovere [Serializable], quindi aggiungere [DataContract] in classe e [DataMember] per la proprietà come di seguito come suggerito
Nagendra Upwanshi

1
Questo aggiunge una quantità enorme di "rumore" alle tue classi ed è essenzialmente inutile (vedi tutti gli altri commenti). Se si sente il bisogno di farlo effettivamente, tuttavia, consiglierei di utilizzare qualcosa come PostSharp per aggiungere il codice durante la compilazione in modo che non ingombrare le tue classi con tutti quegli attributi.
camainc

7

Coppia di opzioni:

  1. Rimuovi [Serializable]dal modello

  2. Aggiungi [DataContract]e [DataMember]al tuo modello insieme a [Serializable]

  3. Aggiungi sotto la riga a App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

3

Un'altra soluzione che può aiutare in caso di JSON.NET. Potrebbe essere sufficiente contrassegnare la classe con l'attributo [Newtonsoft.Json.JsonObject].

Stavo lavorando con classi cs create da xsd e stavo aggiungendo alcune proprietà usando classi parziali. Dopo la serializzazione json, queste proprietà sono state contrassegnate con k_BackingField. Anche le impostazioni di JsonFormatter menzionate in altre risposte hanno aiutato, ma più semplice era contrassegnare la classe parziale con l'attributo [JsonObject].


2

Stavo usando DataContractJsonSerializercon una classe di un altro assembly che aveva l' Serializableattributo. L'output conteneva "k__BackingField". La rimozione Serializabledell'attributo (nell'altro assembly) ha risolto il problema. Non so perché.


0

Supponendo che tu veda questo problema all'interno del tuo progetto MVC, ho scoperto che è piuttosto semplice sostituire l'uso di @ Html.JsonData. Ecco uno snippet di codice che ha funzionato per me in passato:

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

Non così elegante, ma semplice in un pizzico.


0

Ho avuto questo problema quando ho proprietà di riferimento automatico nella mia classe come;

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

E c'è stato un risultato, la persona era amica di se stessa. Mi sono solo assicurato che non ci fossero oggetti autoreferenziali nel mio set di risultati. Spero che questo ti aiuti.



0

nel mio caso questo errore era per la versione Newtonsoft.Json, il server cercava la versione 6.0.0 e io avevo la 11.0, quindi ho dovuto installare la versione 6.0.0


-2

Amici, non dichiarate proprietà come questa:

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

Ma crea vars ausiliari, come i vecchi ...

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}

1
Perché? Potresti dare una risonanza?
Lucenty

@ Lucenty fornisce un JSON come questo .. [{"discreationCode": "x"}], durante la serializzazione.
Ammar Ameerdeen

Ma questo è quello che mi aspetterei: è così che JSON serializza i dati. E penso che il codice con le variabili ausiliarie darà lo stesso risultato.
Lucenty

k_BackingField è stato aggiunto per indicare che una proprietà automatica è stata serializzata. Se esegui il refactoring della proprietà automatica in una proprietà e in un campo di supporto, il problema scomparirà. Penso che ci siano soluzioni migliori in questo thread ma funziona.
timB33
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.