using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class ConfigurableContractResolver : DefaultContractResolver
readonly object contractCreatedPadlock = new object();
event EventHandler<ContractCreatedEventArgs> contractCreated;
void OnContractCreated(JsonContract contract, Type objectType)
EventHandler<ContractCreatedEventArgs> created;
lock (contractCreatedPadlock)
created = contractCreated;
created(this, new ContractCreatedEventArgs(contract, objectType));
public event EventHandler<ContractCreatedEventArgs> ContractCreated
lock (contractCreatedPadlock)
throw new InvalidOperationException("ContractCreated events cannot be added after the first contract is generated.");
contractCreated += value;
lock (contractCreatedPadlock)
throw new InvalidOperationException("ContractCreated events cannot be removed after the first contract is generated.");
contractCreated -= value;
protected override JsonContract CreateContract(Type objectType)
var contract = base.CreateContract(objectType);
OnContractCreated(contract, objectType);
public class ContractCreatedEventArgs : EventArgs
public JsonContract Contract { get; private set; }
public Type ObjectType { get; private set; }
public ContractCreatedEventArgs(JsonContract contract, Type objectType)
this.Contract = contract;
this.ObjectType = objectType;
public static class ConfigurableContractResolverExtensions
public static ConfigurableContractResolver Configure(this ConfigurableContractResolver resolver, EventHandler<ContractCreatedEventArgs> handler)
if (resolver == null || handler == null)
throw new ArgumentNullException();
resolver.ContractCreated += handler;
public string FirstName { get; set; }
public string LastName { get; set; }
public class AllCapsConverter : JsonConverter
public override bool CanConvert(Type objectType) { return objectType == typeof(string); }
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
throw new NotSupportedException();
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
var str = value as string;
var upper = str.ToUpperInvariant();
writer.WriteValue(upper);
public static class JsonContractExtensions
public static void ConfigurePerson(this JsonContract contract)
if (!typeof(Person).IsAssignableFrom(contract.UnderlyingType))
var objectContract = contract as JsonObjectContract;
if (objectContract == null)
var property = objectContract.Properties.Where(p => p.UnderlyingName == "LastName").Single();
property.Converter = new AllCapsConverter();
public static void Test()
var resolver = new ConfigurableContractResolver()
.Configure((s, e) => { e.Contract.ConfigurePerson(); });
var settigs = new JsonSerializerSettings
ContractResolver = resolver,
var serialized = JsonConvert.SerializeObject(person, settigs);
var expected = @"{""FirstName"":""George"",""LastName"":""WASHINGTON""}";
Assert.AreEqual(expected, serialized);
Console.WriteLine(serialized);
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");