Directoryinfo.Enumeratefiles(...) Causes Unauthorizedaccessexception (And Other Exceptions)

Excluding some properties during serialization without changing the original class

For whoever is interested, I decided to use XmlAttributeOverrides, but made them more strong typed (I hate to type property names as strings). Here is the extension method I used for it:

    public static void Add<T>(this XmlAttributeOverrides overrides, Expression<Func<T, dynamic>> propertySelector, XmlAttributes attributes)
{
overrides.Add(typeof(T), propertySelector.BuildString(), attributes);
}

public static string BuildString(this Expression propertySelector)
{
switch (propertySelector.NodeType)
{
case ExpressionType.Lambda:
LambdaExpression lambdaExpression = (LambdaExpression)propertySelector;
return BuildString(lambdaExpression.Body);

case ExpressionType.Convert:
case ExpressionType.Quote:
UnaryExpression unaryExpression = (UnaryExpression)propertySelector;
return BuildString(unaryExpression.Operand);

case ExpressionType.MemberAccess:

MemberExpression memberExpression = (MemberExpression)propertySelector;
MemberInfo propertyInfo = memberExpression.Member;

if (memberExpression.Expression is ParameterExpression)
{
return propertyInfo.Name;
}
else
{
// we've got a nested property (e.g. MyType.SomeProperty.SomeNestedProperty)
return BuildString(memberExpression.Expression) + "." + propertyInfo.Name;
}

default:
// drop out and throw
break;
}
throw new InvalidOperationException("Expression must be a member expression: " + propertySelector.ToString());
}

Then, to ignore an attribute, I can beautifully add it to the ignore list:

    var overrides = new XmlAttributeOverrides();
var ignore = new XmlAttributes { XmlIgnore = true };
overrides.Add<MyClass>(m => m.Id, ignore);
overrides.Add<MyClass>(m => m.DateChanged, ignore);
Type t = typeof(List<MyClass>);
XmlSerializer serial = new XmlSerializer(t, overrides);

Excluding some properties of one class during serialization of the other class that aggregates it


(Disclaimer. Some people might say that serialized fields are like public interface of the class in question, so hiding them in derived classes is kind of a code smell. But I'm not going to address interface implications here, only the way the said goal can achieved.)

There are two features of XmlSerializer that allow to exclude some properties from the output file:

  1. <field>Specified pattern (AKA the old way), e.g. like in here: How to make a value type nullable with .NET XmlSerializer?
  2. ShouldSerialize<field>() pattern, e.g. like here: Xml serialization - Hide null values

Both have some pros and cons in the removing redundant fields down the inheritance tree. Let's see:

<field>Specified pattern. Usage:

public class Example
{
public int x { get; set; }

[XmlIgnore]
public bool xSpecified;

public Example()
{
xSpecified = <set your value for this class>;
}
}

Pros:

  • Can be set in other classes in case if the logic demands it

Cons:

  • Breaks encapsulation of the class in question
  • Contributes to object's size in memory, one boolean per object per property
  • You have to remember to set it to appropiate value, e.g. in constructor

ShouldSerialize<field>() pattern. Usage:

public class Example
{
public int x { get; set; }

public virtual bool ShouldSerializex()
{
return <your logic expression here>;
}
}

Pros:

  • Keeps the encapsulation of the class, allows the logic to be contained in it
  • No additional memory per property
  • More flexible overall

Cons:

  • In this case, having to make it virtual so it would work with derived classes as well, so possibly additional memory for vtable pointer in each object

For the particular issue of mine I utilized both approaches in different places. Self-sufficient classes with several properties needing to be hidden get more advantage out of #2, especially if the project has lists upon lists of lots of their instances. Small classes used to be "brick stones" for composing larger ones might be "dumb" enough to be ignorant whether to serialize some stuff or not, which makes #1 a possible option.

How can I ignore properties of a subclass I dont own during serialization?

Make the subclass:

public class Periodic
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}

Use the custom converter with this code:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Periodic periodic = (Periodic)value;
JToken t = JToken.FromObject(periodic);
t.WriteTo(writer);
}

How to selectively exclude a property from serialization based on the parent class type

As was pointed out by Lasse Karlsen in the comments, if your SharedClass does not have a reference to its parent, there is no way for the ShouldSerializeSomeValue() method in that class to know what the parent class is.

However, if you are using Json.Net 6.0 Release 6 or later, you can work around this by using a custom JsonConverter as a means to selectively omit properties from the shared class (instead of using a ShouldSerialize() method), and then place [JsonConverter] attributes on the SharedClass properties within the appropriate parent classes to indicate which properties should be omitted for that instance.

Here is how the updated example class definitions might look. You'll notice I've marked the SharedClass instance on Foo to indicate it should use a custom converter called OmitPropertiesConverter to omit the SomeValue property. The SharedClass instance on Bar does not use a converter, so that instance will be serialized as normal.

class Foo
{
[JsonConverter(typeof(OmitPropertiesConverter), "SomeValue")]
public SharedClass Shared { get; set; }
}

class Bar
{
public SharedClass Shared { get; set; }
}

class SharedClass
{
public string SomeValue { get; set; }
public string SomeOtherValue { get; set; }
}

Below is the code for the OmitPropertiesConverter. Its constructor accepts a propsToOmit string which is a comma-delimited list of property names to be excluded from the serialization. This gets split into an array for later use in the WriteJson method. The WriteJson method takes the SharedClass value, converts it to a JObject, then programmatically removes the properties which are in the propsToOmit array before writing the JObject to the JsonWriter.

class OmitPropertiesConverter : JsonConverter
{
string[] propsToOmit;

public OmitPropertiesConverter(string propsToOmit)
{
this.propsToOmit = propsToOmit.Split(new char[] {','},
StringSplitOptions.RemoveEmptyEntries);
}

public override bool CanConvert(Type objectType)
{
return (objectType == typeof(SharedClass));
}

public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
JObject jo = JObject.FromObject(value, serializer);

// Note: ToList() is needed here to prevent "collection was modified" error
foreach (JProperty prop in jo.Properties()
.Where(p => propsToOmit.Contains(p.Name))
.ToList())
{
prop.Remove();
}

jo.WriteTo(writer);
}

public override bool CanRead
{
get { return false; }
}

public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

Here is a simple demo program which shows the converter in action:

class Program
{
static void Main(string[] args)
{
var root = new
{
Foo = new Foo
{
Shared = new SharedClass
{
SomeValue = "foo1",
SomeOtherValue = "foo2"
}
},
Bar = new Bar
{
Shared = new SharedClass
{
SomeValue = "bar1",
SomeOtherValue = "bar2"
}
}
};

string json = JsonConvert.SerializeObject(root, Formatting.Indented);
Console.WriteLine(json);
}
}

And here is the output of the above demo. You'll notice that the SomeValue property on the SharedClass instance inside Foo is not included in the output, but it is included on the instance inside Bar.

{
"Foo": {
"Shared": {
"SomeOtherValue": "foo2"
}
},
"Bar": {
"Shared": {
"SomeValue": "bar1",
"SomeOtherValue": "bar2"
}
}
}

Ignore some of the properties during Json.NET serializing but required on others

Try the below code

    [JsonProperty(PropertyName = "componentMainVersion", DefaultValueHandling = DefaultValueHandling.Include)] 
public ushort Version { get; set; }

Required is a different property which makes sure that value for the property is required always

How to exclude property from Json Serialization

If you are using Json.Net attribute [JsonIgnore] will simply ignore the field/property while serializing or deserialising.

public class Car
{
// included in JSON
public string Model { get; set; }
public DateTime Year { get; set; }
public List<string> Features { get; set; }

// ignored
[JsonIgnore]
public DateTime LastModified { get; set; }
}

Or you can use DataContract and DataMember attribute to selectively serialize/deserialize properties/fields.

[DataContract]
public class Computer
{
// included in JSON
[DataMember]
public string Name { get; set; }
[DataMember]
public decimal SalePrice { get; set; }

// ignored
public string Manufacture { get; set; }
public int StockCount { get; set; }
public decimal WholeSalePrice { get; set; }
public DateTime NextShipmentDate { get; set; }
}

Refer http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size for more details

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

You have a few options. I recommend you read the Json.Net documentation article on the subject before reading below.

The article presents two methods:

  1. Create a method that returns a bool value based on a naming convention that Json.Net will follow to determine whether or not to serialize the property.
  2. Create a custom contract resolver that ignores the property.

Of the two, I favor the latter. Skip attributes altogether -- only use them to ignore properties across all forms of serialization. Instead, create a custom contract resolver that ignores the property in question, and only use the contract resolver when you want to ignore the property, leaving other users of the class free to serialize the property or not at their own whim.

Edit To avoid link rot, I'm posting the code in question from the article

public class ShouldSerializeContractResolver : DefaultContractResolver
{
public new static readonly ShouldSerializeContractResolver Instance =
new ShouldSerializeContractResolver();

protected override JsonProperty CreateProperty( MemberInfo member,
MemberSerialization memberSerialization )
{
JsonProperty property = base.CreateProperty( member, memberSerialization );

if( property.DeclaringType == typeof(Employee) &&
property.PropertyName == "Manager" )
{
property.ShouldSerialize = instance =>
{
// replace this logic with your own, probably just
// return false;
Employee e = (Employee)instance;
return e.Manager != e;
};
}

return property;
}
}


Related Topics



Leave a reply



Submit