using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Web.SessionState;
sealed class JsonSkipObjectException : JsonException
public class ShouldSerializeContractResolver : DefaultContractResolver
readonly Predicate<object> shouldSerialize;
readonly SerializationCallback serializationCallback;
readonly SerializationErrorCallback onErrorCallback;
public ShouldSerializeContractResolver(Predicate<object> shouldSerialize)
this.shouldSerialize = shouldSerialize;
this.serializationCallback = (o, context) =>
if (shouldSerialize != null && !this.shouldSerialize(o))
throw new JsonSkipObjectException();
this.onErrorCallback = (o, context, errorContext) =>
if (errorContext.Error is JsonSkipObjectException)
errorContext.Handled = true;
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
var property = base.CreateProperty(member, memberSerialization);
if (shouldSerialize != null)
var oldShouldSerialize = property.ShouldSerialize;
property.ShouldSerialize = (o) =>
if (oldShouldSerialize != null && !oldShouldSerialize(o))
var value = property.ValueProvider.GetValue(o);
if (!this.shouldSerialize(value))
protected override JsonContract CreateContract(Type objectType)
var contract = base.CreateContract(objectType);
contract.OnSerializingCallbacks.Add(serializationCallback);
contract.OnErrorCallbacks.Add(onErrorCallback);
public interface IConditionalSerialization
public class ConditionalSerializationObject : IConditionalSerialization
public bool IsSecret { get; set; }
public string SecretProperty { get { return "should not see me"; } }
public bool ShouldSerializeSecretProperty()
#region IConditionalSerialization Members
bool IConditionalSerialization.ShouldSerialize()
public static void Test()
Test(PreserveReferencesHandling.None);
Test(PreserveReferencesHandling.Arrays);
Test(PreserveReferencesHandling.All);
public static void Test(PreserveReferencesHandling preserveReferencesHandling)
Predicate<object> filter = (o) =>
var conditional = o as IConditionalSerialization;
return conditional == null || conditional.ShouldSerialize();
var settings = new JsonSerializerSettings
ContractResolver = new ShouldSerializeContractResolver(filter),
PreserveReferencesHandling = preserveReferencesHandling,
var ok = new ConditionalSerializationObject { IsSecret = false };
var notOk = new ConditionalSerializationObject { IsSecret = true };
Test(new { Public = ok, Private = notOk }, settings);
Test(new [] { ok, notOk, ok, notOk }, settings);
Test(new[,] {{ ok, notOk, ok, notOk }}, settings);
Test(new { Array = new[,] { { ok, notOk, ok, notOk } } }, settings);
Console.WriteLine("Exception thrown and not caught as expected when serializing root object " + notOk.GetType() + ":");
static void Test<T>(T value, JsonSerializerSettings settings)
Console.WriteLine("Unfiltered object: ");
Console.WriteLine(JToken.FromObject(value));
var serializer = JsonSerializer.CreateDefault(settings);
var token = JToken.FromObject(value, serializer);
Console.WriteLine("Filtered object: ");
Console.WriteLine(token);
if (!token.SelectTokens("..IsSecret").All(t => JToken.DeepEquals(t, (JValue)false)))
throw new InvalidOperationException("token.SelectTokens(\"..IsSecret\").All(t => JToken.DeepEquals(t, (JValue)true))");
if (token.SelectTokens("..SecretProperty").Any())
throw new InvalidOperationException("token.SelectTokens(\"..SecretProperty\").Any()");
Console.WriteLine("Secret objects and properties were successfully filtered.");
public static void Main()