variable tipo serializar procesar objeto net modificar mapear guardar ejemplo asp archivo c# serialization json.net

c# - tipo - Usando JSON.net, ¿cómo evito las propiedades de serialización de una clase derivada, cuando se usa en un contexto de clase base?



serializar objeto c# json (6)

Dado un modelo de datos:

[DataContract] public class Parent { [DataMember] public IEnumerable<ChildId> Children { get; set; } } [DataContract] public class ChildId { [DataMember] public string Id { get; set; } } [DataContract] public class ChildDetail : ChildId { [DataMember] public string Name { get; set; } }

Por razones de conveniencia de implementación, hay ocasiones en que los objetos ChildId en el elemento Parent son, de hecho, objetos ChildDetail . Cuando uso JSON.net para serializar Parent , se escriben con todas las propiedades de ChildDetail .

¿Hay alguna manera de ordenar a JSON.net (o cualquier otro serializador JSON, no estoy lo suficientemente avanzado en el proyecto que se comprometa con uno) que ignore las propiedades derivadas de la clase al serializar como una clase base?

EDITAR: Es importante que cuando serializo directamente la clase derivada, pueda producir todas las propiedades. Solo quiero inhibir el polimorfismo en el objeto Parent .


Al haber encontrado un problema similar, este es el ContractResolver que se me ocurrió:

public class StrictTypeContractResolver : DefaultContractResolver { private readonly Type _targetType; public StrictTypeContractResolver( Type targetType ) => _targetType = targetType; protected override IList<JsonProperty> CreateProperties( Type type, MemberSerialization memberSerialization ) => base.CreateProperties ( _targetType.IsAssignableFrom( type ) ? _targetType : type, memberSerialization ); }

Corta solo las propiedades de los descendientes de targetType , sin afectar las propiedades de sus clases base o de otros tipos a los que las propiedades de targetType puedan hacer referencia. Lo cual, dependiendo de sus necesidades, puede o no ser una mejora sobre las otras respuestas proporcionadas aquí en ese momento.


Mira las respuestas en este hilo similar , particularmente el IgnorableSerializerContractResolver en mi respuesta y la versión lambda más agradable

Uso:

var jsonResolver = new IgnorableSerializerContractResolver(); // ignore single property jsonResolver.Ignore(typeof(Company), "WebSites"); // ignore single datatype jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject)); var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };


No he usado JSON.Net en particular, así que no estoy seguro de que esto te ayude. Si JSON.Net se deriva del sistema de serialización .Net, entonces debería poder agregar el atributo [NonSerialized] a sus propiedades que ahora desea serializar en la clase base. Cuando llama a los métodos de serialización en la clase base, la serialización debe omitir esos elementos.


No se han comparado las implicaciones de rendimiento, pero esta también es una solución funcional y también funciona con objetos anidados / referenciados.

Derived d = new Derived(); string jsonStringD = JsonConvert.SerializeObject(d); Base b = new Base(); JsonConvert.PopulateObject(jsonStringD, b); string jsonStringB = JsonConvert.SerializeObject(b);


Tenía exactamente el mismo problema y busqué la forma de construir el ContractResolver que realmente estaba buscando y que responde mejor a esta pregunta. Esto solo serializa las Propiedades del Tipo T que realmente desea serializar, pero con este ejemplo también puede crear fácilmente enfoques similares:

public class TypeOnlyContractResolver<T> : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); property.ShouldSerialize = instance => property.DeclaringType == typeof (T); return property; } }


Uso un resuelve de contrato personalizado para limitar cuál de mis propiedades serializar. Esto podría apuntarle en la dirección correcta.

p.ej

/// <summary> /// json.net serializes ALL properties of a class by default /// this class will tell json.net to only serialize properties if they MATCH /// the list of valid columns passed through the querystring to criteria object /// </summary> public class CriteriaContractResolver<T> : DefaultContractResolver { List<string> _properties; public CriteriaContractResolver(List<string> properties) { _properties = properties } protected override IList<JsonProperty> CreateProperties( JsonObjectContract contract) { IList<JsonProperty> filtered = new List<JsonProperty>(); foreach (JsonProperty p in base.CreateProperties(contract)) if(_properties.Contains(p.PropertyName)) filtered.Add(p); return filtered; } }

En la función IList de anulación, puede usar el reflejo para completar la lista con solo las propiedades principales quizás.

La resolución de contrato se aplica a su serializador json.net. Este ejemplo es de una aplicación asp.net mvc.

JsonNetResult result = new JsonNetResult(); result.Formatting = Formatting.Indented; result.SerializerSettings.ContractResolver = new CriteriaContractResolver<T>(Criteria);