Tenemos algunos archivos de configuración que se generaron serializando objetos C # con Json.net.
Nos gustaría migrar una propiedad de la clase serializada de ser una propiedad de enumeración simple a una propiedad de clase.
Una forma fácil de hacer esto sería dejar la antigua propiedad enum en la clase y hacer que Json.net lea esta propiedad cuando carguemos la configuración, pero no la vuelva a guardar la próxima vez que serialicemos el objeto. Nos ocuparemos de generar la nueva clase a partir de la enumeración anterior por separado.
¿Existe alguna forma sencilla de marcar (por ejemplo, con atributos) una propiedad de un objeto C #, de modo que Json.net lo ignore SOLAMENTE al serializar, pero lo atenderá al deserializar?
Respuestas:
En realidad, existen varios enfoques bastante simples que puede utilizar para lograr el resultado que desea.
Supongamos, por ejemplo, que tiene sus clases actualmente definidas así:
Y quieres hacer esto:
Para conseguir esto:
Enfoque 1: agregar un método ShouldSerialize
Json.NET tiene la capacidad de serializar condicionalmente propiedades buscando los
ShouldSerialize
métodos correspondientes en la clase.Para usar esta función, agregue un
ShouldSerializeBlah()
método booleano a su clase dondeBlah
se reemplaza con el nombre de la propiedad que no desea serializar. Haz que la implementación de este método siempre regresefalse
.Nota: si le gusta este enfoque pero no quiere enturbiar la interfaz pública de su clase introduciendo un
ShouldSerialize
método, puede usar anIContractResolver
para hacer lo mismo mediante programación. Consulte Serialización de propiedad condicional en la documentación.Enfoque 2: manipular JSON con JObjects
En lugar de usar
JsonConvert.SerializeObject
para hacer la serialización, cargue el objeto de configuración en unJObject
, luego simplemente elimine la propiedad no deseada del JSON antes de escribirlo. Son solo un par de líneas adicionales de código.Enfoque 3: uso inteligente (ab) de los atributos
[JsonIgnore]
atributo a la propiedad que no desea serializar.[JsonProperty]
atributo al establecedor alternativo, dándole el mismo nombre JSON que la propiedad original.Aquí está la
Config
clase revisada :fuente
JsonPropertyAttribute
, desde C # 6.0 puede usar lanameof
palabra clave en lugar de usar "cadenas mágicas". Esto hace que la refactorización sea mucho más fácil e infalible; además, si no cambia el nombre de alguna ocurrencia, el compilador le advertirá de todos modos. Usando el ejemplo de @ Brian, el uso sería el siguiente:[JsonProperty(nameof(ObsoleteSetting))]
Para cualquier situación en la que sea aceptable que su propiedad de solo deserialización se marque como interna, existe una solución notablemente simple que no depende en absoluto de los atributos. Simplemente marque la propiedad como get interno, pero conjunto público:
Esto da como resultado una deserialización correcta utilizando la configuración / resolutores / etc. Predeterminados, pero la propiedad se elimina de la salida serializada.
fuente
get
método público ).internal
ni conprivate
. Siempre está serializado.Me gusta apegarme a los atributos en este, aquí está el método que uso cuando necesito deserializar una propiedad pero no serializarla o viceversa.
PASO 1: cree el atributo personalizado
PASO 2: Cree una renovación de contrato personalizada
PASO 3: agregue un atributo donde la serialización no es necesaria pero la deserialización es
PASO 4 - Úselo
¡Espero que esto ayude! También vale la pena señalar que esto también ignorará las propiedades cuando ocurra la deserialización, cuando estoy deserializando, solo uso el convertidor de la manera convencional.
fuente
GetSerializableMembers
lugar de anularla por completo?return base.GetSerializableMembers(objectType).Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute))).ToList();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() }
Utilice la propiedad del setter:
Espero que esto ayude.
fuente
IgnoreOnSerializing
, igual a la propiedad. Recomiendo usarnameof(IgnoreOnSerializing)
para evitar la cadena mágica, en caso de cambiar el nombre.Después de pasar bastante tiempo buscando cómo marcar una propiedad de clase para ser Desserializable y NO Serializable, descubrí que no existe tal cosa para hacer eso; así que se me ocurrió una solución que combina dos bibliotecas o técnicas de serialización diferentes (System.Runtime.Serialization.Json & Newtonsoft.Json) y funcionó para mí de la siguiente manera:
luego serialice usando "Newtonsoft.Json.JsonConvert.SerializeObject" y De-Serialize usando "System.Runtime.Serialization.Json.DataContractJsonSerializer".
Espero que ayude ...
fuente
Con referencia a la solución de @ ThoHo, usar el setter es en realidad todo lo que se necesita, sin etiquetas adicionales.
Para mí, anteriormente tenía un ID de referencia único, que quería cargar y agregar a la nueva colección de ID de referencia. Al cambiar la definición del Id de referencia para que solo contenga un método setter, que agregó el valor a la nueva colección. Json no puede volver a escribir el valor si la propiedad no tiene un get; método.
Esta clase ahora es compatible con la versión anterior y solo guarda los RefIds para las nuevas versiones.
fuente
Para aprovechar la respuesta de Tho Ho, esto también se puede usar para campos.
fuente
Dependiendo de en qué parte de la aplicación se lleve a cabo y si es solo una propiedad, una forma manual de hacerlo es estableciendo el valor de la propiedad en nulo y luego, en el modelo, puede especificar que la propiedad se ignore si el valor es nulo:
Si está trabajando en una aplicación web ASP.NET Core, puede configurarlo globalmente para todas las propiedades en todos los modelos estableciendo esto en su archivo Startup.cs:
fuente
Si usa JsonConvert, IgnoreDataMemberAttribute está bien. Mi biblioteca estándar no hace referencia a Newton.Json, y uso [IgnoreDataMember] para controlar la serialización de objetos.
Del documento de ayuda de Newton.net .
fuente
La forma más fácil que he encontrado al momento de escribir este artículo es incluir esta lógica en su IContractResolver .
Código de muestra del enlace anterior copiado aquí para la posteridad:
Todas las respuestas son buenas, pero este enfoque parecía ser el más limpio. De hecho, implementé esto buscando un atributo en la propiedad para SkipSerialize y SkipDeserialize para que pueda marcar cualquier clase que controle. ¡Gran pregunta!
fuente