Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude property from serialization via custom attribute (json.net)

I need to be able to control how/whether certain properties on a class are serialized. The simplest case is [ScriptIgnore]. However, I only want these attributes to be honored for this one specific serialization situation I am working on - if other modules downstream in the application also want to serialize these objects, none of these attributes should get in the way.

So my thought is to use a custom attribute MyAttribute on the properties, and initialize the specific instance of JsonSerializer with a hook that knows to look for that attribute.

At first glance, I don't see any of the available hook points in JSON.NET will provide the PropertyInfo for the current property to do such an inspection - only the property's value. Am I missing something? Or a better way to approach this?

like image 882
Rex M Avatar asked Nov 27 '12 15:11

Rex M


People also ask

How do I ignore properties in JSON?

To ignore individual properties, use the [JsonIgnore] attribute. You can specify conditional exclusion by setting the [JsonIgnore] attribute's Condition property. The JsonIgnoreCondition enum provides the following options: Always - The property is always ignored.

How can you prevent a property from being serialized?

You can prevent member variables from being serialized by marking them with the NonSerialized attribute as follows. If possible, make an object that could contain security-sensitive data nonserializable. If the object must be serialized, apply the NonSerialized attribute to specific fields that store sensitive data.

What is a JSON serialization exception?

JsonSerializationException(String, Exception) Initializes a new instance of the JsonSerializationException class with a specified error message and a reference to the inner exception that is the cause of this exception.

Does JSON net serialize private fields?

All fields, both public and private, are serialized and properties are ignored. This can be specified by setting MemberSerialization. Fields on a type with the JsonObjectAttribute or by using the . NET SerializableAttribute and setting IgnoreSerializableAttribute on DefaultContractResolver to false.


2 Answers

Here's a generic reusable "ignore property" resolver based on the accepted answer:

/// <summary> /// Special JsonConvert resolver that allows you to ignore properties.  See https://stackoverflow.com/a/13588192/1037948 /// </summary> public class IgnorableSerializerContractResolver : DefaultContractResolver {     protected readonly Dictionary<Type, HashSet<string>> Ignores;      public IgnorableSerializerContractResolver() {         this.Ignores = new Dictionary<Type, HashSet<string>>();     }      /// <summary>     /// Explicitly ignore the given property(s) for the given type     /// </summary>     /// <param name="type"></param>     /// <param name="propertyName">one or more properties to ignore.  Leave empty to ignore the type entirely.</param>     public void Ignore(Type type, params string[] propertyName) {         // start bucket if DNE         if (!this.Ignores.ContainsKey(type)) this.Ignores[type] = new HashSet<string>();          foreach (var prop in propertyName) {             this.Ignores[type].Add(prop);         }     }      /// <summary>     /// Is the given property for the given type ignored?     /// </summary>     /// <param name="type"></param>     /// <param name="propertyName"></param>     /// <returns></returns>     public bool IsIgnored(Type type, string propertyName) {         if (!this.Ignores.ContainsKey(type)) return false;          // if no properties provided, ignore the type entirely         if (this.Ignores[type].Count == 0) return true;          return this.Ignores[type].Contains(propertyName);     }      /// <summary>     /// The decision logic goes here     /// </summary>     /// <param name="member"></param>     /// <param name="memberSerialization"></param>     /// <returns></returns>     protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {         JsonProperty property = base.CreateProperty(member, memberSerialization);          if (this.IsIgnored(property.DeclaringType, property.PropertyName)         // need to check basetype as well for EF -- @per comment by user576838         || this.IsIgnored(property.DeclaringType.BaseType, property.PropertyName)) {             property.ShouldSerialize = instance => { return false; };         }          return property;     } } 

And usage:

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 }; 
like image 96
drzaus Avatar answered Sep 28 '22 01:09

drzaus


Use the JsonIgnore attribute.

For example, to exclude Id:

public class Person {     [JsonIgnore]     public int Id { get; set; }     public string FirstName { get; set; }     public string LastName { get; set; } } 
like image 36
Ramón Esteban Avatar answered Sep 28 '22 02:09

Ramón Esteban