Jak usunąć k__BackingField z json podczas deserializacji

104

Otrzymuję k_BackingField w zwróconym jsonie po serializacji pliku xml do obiektu c # .net.

Dodałem DataContract i atrybut DataMember do obiektu c # .net, ale potem nic nie widzę po stronie json, po stronie klienta.

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

Przykład zwróconego pliku json:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"
Wypełniam stos
źródło

Odpowiedzi:

45

W rzeczywistości składnia właściwości automatycznej nie jest zalecana, jeśli klasa może być używana w serializacji. Powód, dla którego pole zapasowe jest generowane przez kompilator, może być inny za każdym razem, gdy kompilowany jest kod. Może to powodować problemy ze zgodnością, nawet jeśli w klasie nie zostanie wprowadzona żadna zmiana (wystarczy ponowna kompilacja kodu).

Myślę, że zastosowanie atrybutu DataMember rozwiąże problem w tym przypadku. Ale zalecałbym użycie pełnej składni właściwości, jeśli klasa ma być używana w serializacji.

jags
źródło
Lol, zaimplementował długą wersję i ustawił prywatne pola na klienta.home: Object _fName: "Storefront" _headline: "CEO at StorefrontDoors.NET" _id: "" _industry: ""
Wypełnianie stosu jest tym, co robię
21
dodając ten zapis danych na początek klasy i element datamember do każdej właściwości, która mnie interesuje.
Wypełnianie stosu jest tym, co robię
3
@ AlumCloud.Com +1 dla [DataContract] i [DataMember]. Nie zapomnij dodać: System.Runtime.Serialization
Ian Newland
109

Usuń [Serializable]z zajęć

Safaa Elgendi
źródło
2
Teraz zastanawiam się, dlaczego myślałem, że potrzebuję programu [Serializable] w pierwszej kolejności. Moja serializacja Xml działa bez niego, a JSON działa bez niego.
Rhyous
11
To nie działa z usługami WCF. Podczas zwracania ładunku przy użyciu usług RESTful nie daje to żadnych danych, jeśli usuniesz [Serializable]. Dodaj System.Runtime.Serialization i użyj [DataContract] dla klasy, [DataMember] dla właściwości.
Ian Newland
Ta odpowiedź ORAZ komentarz Iana wydaje się obejmować oba przypadki. Do WCF czy nie do WCF, oto jest pytanie.
granadaCoder
1
@Rhyous - w Web API nie potrzebujesz [Serializable], ponieważ Web API jest skonfigurowane przy założeniu, że będziesz serializować i zwracać swoje obiekty (ponieważ to w zasadzie cała idea) - w innych aplikacjach C # zazwyczaj wymaga serializacji, aby rozróżniać obiekty, które można serializować
Jon Story
Dziękuję, utknąłem [Serializable], więc dodanie pól pomocniczych pomogło.
ohmusama,
59

Domyślny serializator WebApi doda składnię „__BackingField:” do właściwości automatycznych języka C #. Dodaj to do swojej konsoli WebConfig w App_Start, aby uzyskać bardziej przejrzysty plik JSON, którego możesz szukać.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Dan
źródło
3
To rozwiązało problem. Myślę, że właściwości auto są czyste. Używanie pól pomocniczych wszędzie wydaje się głupie. i wprowadza dużo bałaganu, a czasem zamieszania.
Romesh D. Niriella
To zadziałało dla mnie. W moim przypadku miałem istniejącą klasę, która była już używana przez usługi sieciowe WCF i ASMX, więc nie mogłem po prostu zmienić jej dla mojego nowego projektu WebAPI.
samiup
4
Pytanie brzmi, dlaczego serializator WebApi doda domyślnie to „__BackingField:”?
Teoman shipahi
dobre rozwiązanie. w moim przypadku muszę użyć [Serializable] save do memcache. Wymagane jest serializowanie.
Bình Nguyễn Quang
2
Co bym zrobił bez StackOverflow? Dzięki.
camainc
35

Mamy pewne obiekty, które są oznaczone jako [Serializable]tak, aby można je było serializować przy użyciu tradycyjnych metod, ale które musimy czysto serializować w formacie JSON do użytku z interfejsem API sieci Web. Ustawienie IgnoreSerializableAttributena truepowstrzyma Newtonsoft.Json przed zachowaniem się jak serialisers Microsoftu, a zamiast tego po prostu serializuje właściwości publiczne.

TLDR: Dodaj to do WebApiConfig.cs:

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

Moderator: Zamiast usuwać naprawdę dobrą odpowiedź na pytanie, które zostało zadane kilka razy, usuń zduplikowane pytanie. To jest prawidłowa odpowiedź na ważne pytanie.

Richard
źródło
3
To powinna być właściwa odpowiedź. Usunięcie serializacji lub użycie atrybutów datacontract i datamember nie zawsze jest właściwym rozwiązaniem.
Houssam Hamdan
Wielu z nas, w tym OP, nie używa Webapi, MVVM, ani czegokolwiek, o co wam chodzi. Co to jest app_start i webapiconfig, gdy mam normalną usługę WCF mydła z service.svc?
Christian,
10

Prosty, łatwy i przyzwoity sposób na ujawnienie danych Musimy udostępnić dane w obiekcie w czytelnym i spójnym formacie


Najpierw usuń [serializowalny]

    [Serializable]

teraz dodaj [DataContract] w klasie i [DataMember] dla właściwości jak w poniższym przykładzie

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

Mam nadzieję, że ta pomoc
dzięki.

Nagendra Upwanshi
źródło
1
W przypadku korzystania z interfejsu API sieci Web nie ma potrzeby dodawania atrybutów DataContract i DataMember - wystarczy zwrócić obiekt, a zostanie on zserializowany automatycznie.
Jon Story
Jeśli ktoś zaczyna programowanie od zera, to świetnie będzie skorzystać z interfejsu API sieci Web, który zapewni zwracany typ Object, nie będzie wymagał żadnego typu rzutowania do ujawnienia klientowi. Ale jeśli chodzi o pytanie @ AlumCloud.com, jeśli jest w istniejącej aplikacji, więc rozwiązanie jego problemu będzie przez Najpierw usuń [Serializable], a następnie dodaj [DataContract] w klasie i [DataMember] dla nieruchomości jak poniżej, jak sugerowano
Nagendra Upwanshi
1
Dodaje to ogromną ilość „szumu” do twoich zajęć i jest zasadniczo niepotrzebne (zobacz wszystkie inne komentarze). Jeśli jednak ktoś czuje potrzebę zrobienia tego, zalecałbym użycie czegoś takiego jak PostSharp, aby dodać kod podczas kompilacji, aby nie zaśmiecał twoich klas wszystkimi tymi atrybutami.
camainc
7

Kilka opcji:

  1. Usuń [Serializable]z modelu

  2. Dodaj [DataContract]i [DataMember]do swojego modelu wraz z [Serializable]

  3. Dodaj poniższą linię do App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Jayaprakash Muthugopal
źródło
3

Kolejne rozwiązanie, które może pomóc w przypadku JSON.NET. Wystarczy oznaczyć klasę atrybutem [Newtonsoft.Json.JsonObject].

Pracowałem z klasami cs zbudowanymi z xsd i dodawałem niektóre właściwości za pomocą klas częściowych. Po serializacji json te właściwości zostały oznaczone k_BackingField. Ustawienia JsonFormatter wspomniane w innych odpowiedziach również pomogły, ale prostsze było oznaczenie częściowej klasy atrybutem [JsonObject].

sarh
źródło
2

Używałem DataContractJsonSerializerz klasą z innego zestawu, który miał Serializableatrybut. Dane wyjściowe zawierały „k__BackingField”. Usunięcie Serializableatrybutu (w innym zestawie) naprawiło ten problem. Nie pewny dlaczego.

Little Endian
źródło
0

Zakładając, że widzisz ten problem w swoim projekcie MVC, stwierdziłem, że zastąpienie użycia @ Html.JsonData jest całkiem proste. Oto fragment kodu, który działał dla mnie w przeszłości:

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

Nie tak eleganckie, ale proste w mgnieniu oka.

Ryan Roark
źródło
0

Wystąpił ten problem, gdy w mojej klasie są właściwości odniesienia do siebie, takie jak;

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

I był rezultat, osoba była ze sobą zaprzyjaźniona. Po prostu upewniłem się, że w moim zestawie wyników nie ma obiektów odwołujących się do siebie. Mam nadzieję że to pomoże.

Teoman shipahi
źródło
0

Musiałem użyć atrybutów [Serializable], więc ich usunięcie nie wchodziło w grę.

XmlSerializer ignoruje [XmlAttribute] w WebApi

Powyższa rezolucja rozwiązała to za mnie.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
źródło
0

w moim przypadku ten błąd był dla wersji Newtonsoft.Json, serwer szukał wersji 6.0.0 i miałem 11.0 więc musiałem zainstalować wersję 6.0.0

Andres Guillen
źródło
-2

Przyjaciele, nie deklarujcie takich właściwości:

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

Ale stwórz pomocnicze zmienne, takie jak stare ...

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}
Humberto Gonçalves de Almeida
źródło
1
Czemu? Czy mógłbyś dać rezonans?
Lucenty
@Lucenty daje taki kod JSON ... [{"discationCode": "x"}] podczas serializacji.
Ammar Ameerdeen
Ale tego bym się spodziewał - tak serializuje dane JSON. I myślę, że kod z pomocniczymi zmiennymi da ten sam wynik.
Lucenty,
Dodano k_BackingField, aby wskazać, że właściwość automatyczna została zserializowana. Jeśli zmienisz właściwość auto na właściwość i pole zapasowe, problem zniknie. Myślę, że w tym wątku są lepsze rozwiązania, ale to działa.
timB33