Cómo eliminar k__BackingField de json cuando Deserialize

104

Obtengo k_BackingField en mi json devuelto después de serializar un archivo xml en un objeto .net c #.

Agregué el DataContract y el atributo DataMember al objeto .net c # pero luego no obtengo nada en el json, cliente.

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

Ejemplo del json devuelto:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"
Llenar la pila es lo que HAGO
fuente

Respuestas:

45

En realidad, no se recomienda la sintaxis de propiedad automática si la clase se puede utilizar en la serialización. La razón es que el campo de respaldo es generado por el compilador, que puede ser diferente cada vez que se compila el código. Esto puede causar problemas de incompatibilidad incluso si no se realiza ningún cambio en la clase (simplemente recompilando el código).

Creo que la aplicación del atributo DataMember solucionará el problema en este caso. Pero recomendaría usar la sintaxis de propiedad completa, si la clase necesita usarse en la serialización.

jags
fuente
Lol, implementó la versión larga y configuró los campos privados para el cliente.home: Object _fName: "Storefront" _headline: "CEO en StorefrontDoors.NET" _id: "" _industry: ""
Llenar la pila es lo que HAGO
21
agregando ese contrato de datos a la parte superior de la clase y miembro de datos a cada propiedad en la que estoy interesado trabajó.
Llenar la pila es lo que HAGO
3
@ AlumCloud.Com +1 para [DataContract] y [DataMember]. No olvide agregar: System.Runtime.Serialization
Ian Newland
109

Eliminar [Serializable]de tu clase

Safaa Elgendi
fuente
2
Ahora me pregunto por qué pensé que necesitaba [Serializable] en primer lugar. Mi serialización Xml funciona sin y JSON funciona sin él.
Rhyous
11
Esto no funciona con WCF Services. Cuando se devuelve una carga útil utilizando servicios RESTful, esto no produce ningún dato si elimina [Serializable]. Agregue System.Runtime.Serialization y use [DataContract] para la clase, [DataMember] para las propiedades.
Ian Newland
Esta respuesta Y el comentario de Ian parecen cubrir ambos casos. Para WCF o no para WCF, esa es la cuestión.
granadaCoder
1
@Rhyous: en la API web no necesita [Serializable], porque la API web está configurada con la suposición de que va a serializar y devolver sus objetos (ya que esa es básicamente la idea completa); en otras aplicaciones C # generalmente necesita serializable para diferenciar objetos serializables
Jon Story
Gracias, me quedé atrapado [Serializable], por lo que agregar campos de respaldo ayudó.
ohmusama
59

El serializador WebApi predeterminado agregará esa sintaxis "__BackingField:" a las propiedades automáticas de c #. Agregue esto a su WebConfig en App_Start para obtener el json de aspecto más limpio que podría estar buscando.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Dan
fuente
3
Esto solucionó el problema. Creo que las propiedades de los automóviles están limpias. Usar campos de respaldo en todas partes parece estúpido. e introduce mucho desorden y, a veces, confusión.
Romesh D. Niriella
Esto funcionó para mí. En mi caso, tenía una clase existente que ya estaba siendo utilizada por los servicios web WCF y ASMX, por lo que no podía simplemente cambiarla para mi nuevo proyecto WebAPI.
samiup
4
La pregunta es ¿por qué demonios el serializador WebApi agregará ese "__BackingField:" de forma predeterminada?
Teoman shipahi
buena solución. en mi caso, necesito usar [Serializable] save en Memcache. Se requiere serializable.
Bình Nguyễn Quang
2
¿Qué haría sin StackOverflow? Gracias.
camainc
35

Tenemos algunos objetos que están marcados [Serializable]para que se puedan serializar utilizando métodos tradicionales, pero que necesitamos serializarlos limpiamente en JSON para usarlos con la API web. Establecer IgnoreSerializableAttributeen trueimpedirá que Newtonsoft.Json se comporte como los serializadores de Microsoft y, en su lugar, solo serializará las propiedades públicas.

TLDR: agregue esto a WebApiConfig.cs:

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

Moderador: En lugar de eliminar una respuesta realmente buena a una pregunta que se ha formulado varias veces, elimine la pregunta duplicada. Esta es una respuesta válida a una pregunta válida.

Ricardo
fuente
3
Esta debería ser la respuesta correcta. La eliminación de la serialización o el uso de los atributos de datamember y datamember no siempre es la solución correcta.
Houssam Hamdan
Muchos de nosotros, incluido OP, no estamos usando Webapi o MVVM o lo que sea que estén hablando. ¿Qué es app_start y webapiconfig cuando tengo un servicio WCF de jabón normal con service.svc?
Christian
10

Una forma sencilla, fácil y decente de exponer datos Necesitamos exponer los datos en el objeto a un formato fácil de leer y coherente


Primero elimine [Serializable]

    [Serializable]

ahora agregue [DataContract] en la clase y [DataMember] para la propiedad como el siguiente ejemplo

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

Espero que esto ayude
Gracias.

Nagendra Upwanshi
fuente
1
Si usa Web API, no es necesario agregar los atributos DataContract y DataMember en absoluto; simplemente devuelva el objeto y se serializará automáticamente.
Jon Story
Si alguien comienza el desarrollo desde cero, será genial usar la API web, que proporcionará el tipo de retorno del objeto, no requerirá ningún tipo de conversión de tipos para exponer al cliente. Pero para la pregunta de @ AlumCloud.com, si está en la aplicación existente, la solución para su problema será Primero elimine [Serializable] luego agregue [DataContract] en la clase y [DataMember] para la propiedad como se sugiere a continuación
Nagendra Upwanshi
1
Esto agrega una enorme cantidad de "ruido" a sus clases y es esencialmente innecesario (vea todos los demás comentarios). Sin embargo, si uno siente la necesidad de hacer esto, le recomendaría usar algo como PostSharp para agregar el código durante la compilación para que no abarrote sus clases con todos esos atributos.
camainc
7

Un par de opciones:

  1. Quitar [Serializable]del modelo

  2. Agregue [DataContract]y [DataMember]a su modelo junto con [Serializable]

  3. Añada la siguiente línea a App_Start/WebApiConfig.cs

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

Otra solución que puede ayudar en el caso de JSON.NET. Puede ser suficiente marcar la clase con el atributo [Newtonsoft.Json.JsonObject].

Estaba trabajando con clases cs creadas a partir de xsd y estaba agregando algunas propiedades usando clases parciales. Después de la serialización json, estas propiedades se marcaron con k_BackingField. La configuración de JsonFormatter mencionada en otras respuestas también ayudó, pero más simple fue marcar una clase parcial con el atributo [JsonObject].

sarh
fuente
2

Estaba usando DataContractJsonSerializercon una clase de otro ensamblado que tenía el Serializableatributo. La salida contenía "k__BackingField". La eliminación del Serializableatributo (en el otro ensamblaje) solucionó esto. No estoy seguro de por qué.

Little Endian
fuente
0

Suponiendo que vea este problema dentro de su proyecto MVC, descubrí que es bastante simple reemplazar el uso de @ Html.JsonData. Aquí hay un fragmento de código que me ha funcionado en el pasado:

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

No tan elegante, pero simple en un apuro.

Ryan Roark
fuente
0

Tuve este problema cuando tengo propiedades de autorreferencia en mi clase, como;

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

Y hubo un resultado, la persona era amiga de sí misma. Solo me aseguré de que no hubiera objetos de autorreferencia en mi conjunto de resultados. Espero que esto ayude.

Teoman shipahi
fuente
0

Tuve que usar los atributos [Serializable], por lo que eliminarlos no era una opción.

XmlSerializer ignora [XmlAttribute] en WebApi

La resolución anterior me lo resolvió.

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

en mi caso este error fue para la versión Newtonsoft.Json, el servidor buscó la versión 6.0.0 y yo tenía la 11.0, así que tuve que instalar la versión 6.0.0

Andrés Guillén
fuente
-2

Amigos, no declaren propiedades como esta:

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

Pero, crea vars auxiliares, como antes ...

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}
Humberto Gonçalves de Almeida
fuente
1
¿Por qué? ¿Podrías darme una resonancia?
Lucenty
@Lucenty da un JSON como este .. [{"discreationCode": "x"}], al serializar.
Ammar Ameerdeen
Pero esto es lo que esperaría: así es como JSON serializa los datos. Y creo que el código con vars auxiliares dará el mismo resultado.
Lucenty
Se ha agregado k_BackingField para indicar que se ha serializado una propiedad automática. Si refactoriza la propiedad automática a una propiedad y un campo de respaldo, el problema desaparecerá. Creo que hay mejores soluciones en este hilo, pero esto funciona.
timB33