Como remover k__BackingField de json ao desserializar

104

Estou recebendo o k_BackingField em meu json retornado após serializar um arquivo xml para um objeto .net c #.

Eu adicionei o DataContract e o atributo DataMember ao objeto .net c #, mas não recebo nada no json, client end.

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

Exemplo do json retornado:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"
Preencher a pilha é o que eu FAÇO
fonte

Respostas:

45

Na verdade, a sintaxe de propriedade automática não é recomendada se a classe puder ser usada na serialização. O motivo pelo qual o campo de apoio é gerado pelo compilador pode ser diferente a cada vez que o código é compilado. Isso pode causar problemas de incompatibilidade, mesmo se nenhuma alteração for feita na classe (apenas recompilar o código).

Acho que a aplicação do atributo DataMember resolverá o problema neste caso. Mas eu recomendaria usar sintaxe de propriedade completa, se a classe precisar ser usada na serialização.

entalhes
fonte
Lol, implementou a versão longa e definiu os campos privados para o client.home: Object _fName: "Storefront" _headline: "CEO at StorefrontDoors.NET" _id: "" _industry: ""
Filling The Stack é o que EU FAÇO
21
adicionando aquele datacontract ao topo da classe e datamember para cada propriedade que estou interessado trabalhou.
Filling The Stack é o que EU FAÇO
3
@ AlumCloud.Com +1 para [DataContract] e [DataMember]. Não se esqueça de adicionar: System.Runtime.Serialization
Ian Newland
109

Remover [Serializable]da sua classe

Safaa Elgendi
fonte
2
Agora estou me perguntando por que pensei que precisava de [Serializable] em primeiro lugar. Minha serialização Xml funciona sem e JSON funciona sem ela.
Rhyous
11
Isso não funciona com os serviços WCF. Ao retornar uma carga útil usando serviços RESTful, isso não produz nenhum dado se você remover [Serializable]. Adicione System.Runtime.Serialization e use [DataContract] para a classe, [DataMember] para propriedades.
Ian Newland
Esta resposta E o comentário de Ian parecem cobrir ambos os casos. Para o WCF ou não para o WCF, essa é a questão.
granadaCoder
1
@Rhyous - na API da Web você não precisa de [Serializable], porque a API da Web é configurada com a suposição de que você serializará e retornará seus objetos (já que essa é basicamente a ideia inteira) - em outros aplicativos C # você geralmente precisa Serializable para diferenciar objetos serializáveis
Jon Story
Obrigado, eu estava preso [Serializable], então adicionar campos de apoio ajudou.
ohmusama
59

O serializador WebApi padrão adicionará a sintaxe "__BackingField:" às propriedades automáticas do c #. Adicione-o ao WebConfig em App_Start para obter o json de aparência mais limpa que você pode estar procurando.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Dan
fonte
3
Isso resolveu o problema. Acho que as propriedades do automóvel são limpas. Usar campos de apoio em todos os lugares parece estúpido. e introduz muita desordem e, às vezes, confusão.
Romesh D. Niriella,
Isso funcionou para mim. No meu caso, eu tinha uma classe existente que já estava sendo usada pelos webservices WCF e ASMX, então não pude apenas alterá-la para meu novo projeto WebAPI.
samiup
4
A questão é por que diabos o serializador WebApi adicionará esse "__BackingField:" por padrão?
Teoman shipahi
boa solução. no meu caso, preciso usar o salvamento [Serializable] no memcache. Serializável é necessário.
Bình Nguyễn Quang,
2
O que eu faria sem StackOverflow? Obrigado.
camainc
35

Temos alguns objetos que são marcados como [Serializable]para que possam ser serializados usando métodos tradicionais, mas que precisamos serializar de forma limpa em JSON para uso com a Web API. Definir IgnoreSerializableAttributecomo trueimpedirá o Newtonsoft.Json de se comportar como serializadores da Microsoft e, em vez disso, apenas serializará as propriedades públicas.

TLDR: adicione a WebApiConfig.cs:

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

Moderador: Em vez de excluir uma resposta realmente boa a uma pergunta que foi feita várias vezes, exclua a pergunta duplicada. Esta é uma resposta válida para uma pergunta válida.

Richard
fonte
3
Esta deve ser a resposta certa. Remover a serialização ou usar atributos de datacontract e datamember nem sempre é a solução correta.
Houssam Hamdan
Muitos de nós não estão, incluindo OP, usando Webapi ou MVVM ou o que quer que vocês estejam falando. O que são app_start e webapiconfig quando tenho um serviço WCF soap normal com service.svc?
Christian
10

Forma simples, fácil e decente de expor os dados Precisamos expor os dados no objeto para um formato fácil de ler e consistente


Primeiro remova [Serializable]

    [Serializable]

agora adicione [DataContract] na classe e [DataMember] para a propriedade como o exemplo abaixo

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

Espero esta ajuda,
obrigado.

Nagendra Upwanshi
fonte
1
Se estiver usando a API Web, não há necessidade de adicionar os atributos DataContract e DataMember - basta retornar o objeto e ele será serializado automaticamente.
Jon Story de
Se alguém estiver iniciando o desenvolvimento do zero, será ótimo usar a API Web, que fornecerá o tipo de retorno Object, não exigirá nenhum tipo de conversão de tipo para expor ao cliente. Mas para a pergunta @ AlumCloud.com, se ele estiver no aplicativo existente, a solução para o problema será primeiro remover [Serializable] e depois adicionar [DataContract] na classe e [DataMember] para a propriedade como abaixo, conforme sugerido
Nagendra Upwanshi
1
Isso adiciona uma quantidade enorme de "ruído" às suas aulas e é essencialmente desnecessário (veja todos os outros comentários). Se alguém sentir a necessidade de realmente fazer isso, no entanto, eu recomendaria usar algo como PostSharp para adicionar o código para você durante a compilação, de modo que ele não sobrecarregue suas classes com todos esses atributos.
camainc
7

Algumas opções:

  1. Remover [Serializable]do modelo

  2. Adicione [DataContract]e [DataMember]ao seu modelo junto com [Serializable]

  3. Adicionar linha abaixo para App_Start/WebApiConfig.cs

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

Outra solução que pode ajudar no caso do JSON.NET. Pode ser o suficiente para marcar a classe com o atributo [Newtonsoft.Json.JsonObject].

Eu estava trabalhando com classes cs criadas a partir do xsd e adicionando algumas propriedades usando classes parciais. Após a serialização json, essas propriedades foram marcadas com k_BackingField. As configurações de JsonFormatter mencionadas em outras respostas também ajudaram, mas mais simples foi marcar a classe parcial com o atributo [JsonObject].

sarh
fonte
2

Eu estava usando DataContractJsonSerializercom uma classe de outra montagem que tinha o Serializableatributo. A saída continha "k__BackingField". Remover o Serializableatributo (na outra montagem) corrigiu isso. Não sei por quê.

Pequeno endian
fonte
0

Supondo que você veja esse problema dentro de seu projeto MVC, descobri que é muito simples substituir o uso de @ Html.JsonData. Aqui está um trecho de código que funcionou para mim no passado:

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

Não tão elegante, mas simples em uma pitada.

Ryan Roark
fonte
0

Eu tive esse problema quando tenho propriedades de autorreferência em minha classe, como;

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

E teve um resultado, a pessoa ficou amiga de si mesma. Eu apenas me certifiquei de que não havia objetos de autorreferência em meu conjunto de resultados. Espero que isto ajude.

Teoman shipahi
fonte
0

Tive que usar os atributos [Serializable], portanto, removê-los não era uma opção.

XmlSerializer ignora [XmlAttribute] em WebApi

A resolução acima resolveu para mim.

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

no meu caso esse erro foi para a versão Newtonsoft.Json, o servidor procurou a versão 6.0.0 e eu tinha a 11.0, então tive que instalar a versão 6.0.0

Andres Guillen
fonte
-2

Amigos, não declare propriedades como esta:

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

Mas, crie vars auxiliares, como o antigo ....

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}
Humberto Gonçalves de Almeida
fonte
1
Por quê? Você poderia dar uma ressonância?
Lucenty
@Lucenty dá um JSON como este .. [{"discreationCode": "x"}], ao serializar.
Ammar Ameerdeen,
Mas isso é o que eu esperava - é assim que JSON serializa os dados. E acho que o código com vars auxiliares dará o mesmo resultado.
Lucenty,
k_BackingField foi adicionado para indicar que uma propriedade automática foi serializada. Se você refatorar a propriedade automática em uma propriedade e um campo de apoio, o problema desaparecerá. Eu acho que há melhores soluções neste tópico, mas funciona.
timB33