private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
		{
			OnSerializing(writer, contract, value);

			_serializeStack.Add(value);

			WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);

			int initialDepth = writer.Top;

			for (int index = 0; index < contract.Properties.Count; index++)
			{
				JsonProperty property = contract.Properties[index];
				try
				{
					object memberValue;
					JsonContract memberContract;

					if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
						continue;

					property.WritePropertyName(writer);
					SerializeValue(writer, memberValue, memberContract, property, contract, member);
				}
				catch (Exception ex)
				{
					if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
						HandleError(writer, initialDepth);
					else
						throw;
				}
			}

			writer.WriteEndObject();

			_serializeStack.RemoveAt(_serializeStack.Count - 1);

			OnSerialized(writer, contract, value);
		}
		private void SetExtensionData(JsonObjectContract contract, JsonReader reader, string memberName, object o)
		{
			if (contract.ExtensionDataSetter != null)
			{
				try
				{
					JToken extensionDataValue = JToken.ReadFrom(reader);

					contract.ExtensionDataSetter(o, memberName, extensionDataValue);
				}
				catch (Exception ex)
				{
					throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex);
				}
			}
			else
			{
				reader.Skip();
			}
		}
		private void EndObject(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, Dictionary<JsonProperty, PropertyPresence> propertiesPresence)
		{
			if (propertiesPresence != null)
			{
				foreach (var propertyPresence in propertiesPresence)
				{
					JsonProperty property = propertyPresence.Key;
					PropertyPresence presence = propertyPresence.Value;

					if (presence == PropertyPresence.None || presence == PropertyPresence.Null)
					{
						try
						{
							Required resolvedRequired = property._required ?? contract.ItemRequired ?? Required.Default;

							switch (presence)
							{
								case PropertyPresence.None:
									if (resolvedRequired == Required.AllowNull || resolvedRequired == Required.Always)
										throw JsonSerializationException.Create(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));

									if (property.PropertyContract == null)
										property.PropertyContract = GetContractSafe(property.PropertyType);

									if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && property.Writable)
										property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType));
									break;
								case PropertyPresence.Null:
									if (resolvedRequired == Required.Always)
										throw JsonSerializationException.Create(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
									break;
							}
						}
						catch (Exception ex)
						{
							if (IsErrorHandled(newObject, contract, property.PropertyName, reader as IJsonLineInfo, reader.Path, ex))
								HandleError(reader, true, initialDepth);
							else
								throw;
						}
					}
				}
			}
		}
		private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id)
		{
			OnDeserializing(reader, contract, newObject);

			// only need to keep a track of properies presence if they are required or a value should be defaulted if missing
			Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None) : null;

			if (id != null)
				AddReference(reader, id, newObject);

			int initialDepth = reader.Depth;

			bool finished = false;
			do
			{
				switch (reader.TokenType)
				{
					case JsonToken.PropertyName:
						{
							string memberName = reader.Value.ToString();

							try
							{
								// attempt exact case match first
								// then try match ignoring case
								JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);

								if (property == null)
								{
									if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
										TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType)), null);

									if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
										throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType.Name));

									if (!reader.Read())
										break;

									SetExtensionData(contract, reader, memberName, newObject);
									continue;
								}

								if (property.PropertyContract == null)
									property.PropertyContract = GetContractSafe(property.PropertyType);

								JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, member);

								if (!ReadForType(reader, property.PropertyContract, propertyConverter != null))
									throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

								SetPropertyPresence(reader, property, propertiesPresence);

								// set extension data if property is ignored or readonly
								if (!SetPropertyValue(property, propertyConverter, contract, member, reader, newObject))
									SetExtensionData(contract, reader, memberName, newObject);
							}
							catch (Exception ex)
							{
								if (IsErrorHandled(newObject, contract, memberName, reader as IJsonLineInfo, reader.Path, ex))
									HandleError(reader, true, initialDepth);
								else
									throw;
							}
						}
						break;
					case JsonToken.EndObject:
						finished = true;
						break;
					case JsonToken.Comment:
						// ignore
						break;
					default:
						throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
				}
			} while (!finished && reader.Read());

			if (!finished)
				ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object.");

			EndObject(newObject, reader, contract, initialDepth, propertiesPresence);

			OnDeserialized(reader, contract, newObject);
			return newObject;
		}
		public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultConstructor)
		{
			object newObject = null;

			if (!objectContract.IsInstantiable)
				throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType));

			if (objectContract.OverrideConstructor != null)
			{
				if (objectContract.OverrideConstructor.GetParameters().Length > 0)
				{
					createdFromNonDefaultConstructor = true;
					return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.OverrideConstructor, id);
				}

				newObject = objectContract.OverrideConstructor.Invoke(null);
			}
			else if (objectContract.DefaultCreator != null && (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedConstructor == null))
			{
				// use the default constructor if it is...
				// public
				// non-public and the user has change constructor handling settings
				// non-public and there is no other constructor
				newObject = objectContract.DefaultCreator();
			}
			else if (objectContract.ParametrizedConstructor != null)
			{
				createdFromNonDefaultConstructor = true;
				return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedConstructor, id);
			}

			if (newObject == null)
				throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType));

			createdFromNonDefaultConstructor = false;
			return newObject;
		}
		private IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
		{
			IDictionary<JsonProperty, object> propertyValues = new Dictionary<JsonProperty, object>();
			bool exit = false;
			do
			{
				switch (reader.TokenType)
				{
					case JsonToken.PropertyName:
						string memberName = reader.Value.ToString();

						// attempt exact case match first
						// then try match ignoring case
						JsonProperty property = contract.ConstructorParameters.GetClosestMatchProperty(memberName) ?? contract.Properties.GetClosestMatchProperty(memberName);

						if (property != null)
						{
							if (property.PropertyContract == null)
								property.PropertyContract = GetContractSafe(property.PropertyType);

							JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, containerProperty);

							if (!ReadForType(reader, property.PropertyContract, propertyConverter != null))
								throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

							if (!property.Ignored)
							{
								if (property.PropertyContract == null)
									property.PropertyContract = GetContractSafe(property.PropertyType);

								object propertyValue;
								if (propertyConverter != null && propertyConverter.CanRead)
									propertyValue = DeserializeConvertable(propertyConverter, reader, property.PropertyType, null);
								else
									propertyValue = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null);

								propertyValues[property] = propertyValue;
							}
							else
							{
								reader.Skip();
							}
						}
						else
						{
							if (!reader.Read())
								throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

							if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
								TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType)), null);

							if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
								throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, objectType.Name));

							reader.Skip();
						}
						break;
					case JsonToken.Comment:
						break;
					case JsonToken.EndObject:
						exit = true;
						break;
					default:
						throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
				}
			} while (!exit && reader.Read());

			return propertyValues;
		}
		private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id)
		{
			ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");

			Type objectType = contract.UnderlyingType;

			if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
				TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using a non-default constructor '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, constructorInfo)), null);

			IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType);

			IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object) null);
			IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();

			foreach (var propertyValue in propertyValues)
			{
				ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, propertyValue.Key.UnderlyingName).Key;
				if (matchingConstructorParameter != null)
					constructorParameters[matchingConstructorParameter] = propertyValue.Value;
				else
					remainingPropertyValues.Add(propertyValue);
			}

			object createdObject = constructorInfo.Invoke(constructorParameters.Values.ToArray());

			if (id != null)
				AddReference(reader, id, createdObject);

			OnDeserializing(reader, contract, createdObject);

			// go through unused values and set the newly created object's properties
			foreach (var remainingPropertyValue in remainingPropertyValues)
			{
				JsonProperty property = remainingPropertyValue.Key;
				object value = remainingPropertyValue.Value;

				if (ShouldSetPropertyValue(remainingPropertyValue.Key, remainingPropertyValue.Value))
				{
					property.ValueProvider.SetValue(createdObject, value);
				}
				else if (!property.Writable && value != null)
				{
					// handle readonly collection/dictionary properties
					JsonContract propertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType);

					if (propertyContract.ContractType == JsonContractType.Array)
					{
						var propertyArrayContract = (JsonArrayContract) propertyContract;

						object createdObjectCollection = property.ValueProvider.GetValue(createdObject);
						if (createdObjectCollection != null)
						{
							IWrappedCollection createdObjectCollectionWrapper = propertyArrayContract.CreateWrapper(createdObjectCollection);
							IWrappedCollection newValues = propertyArrayContract.CreateWrapper(value);

							foreach (var newValue in newValues)
							{
								createdObjectCollectionWrapper.Add(newValue);
							}
						}
					}
					else if (propertyContract.ContractType == JsonContractType.Dictionary)
					{
						var dictionaryContract = (JsonDictionaryContract) propertyContract;

						object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
						if (createdObjectDictionary != null)
						{
							IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary) createdObjectDictionary;
							IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary) value;

							foreach (DictionaryEntry newValue in newValues)
							{
								targetDictionary.Add(newValue.Key, newValue.Value);
							}
						}
					}
				}
			}

			OnDeserialized(reader, contract, createdObject);
			return createdObject;
		}
		private void GenerateObjectSchema(Type type, JsonObjectContract contract)
		{
			CurrentSchema.Properties = new Dictionary<string, JsonSchema>();
			foreach (var property in contract.Properties)
			{
				if (!property.Ignored)
				{
					bool optional = property.NullValueHandling == NullValueHandling.Ignore || HasFlag(property.DefaultValueHandling.GetValueOrDefault(), DefaultValueHandling.Ignore) || property.ShouldSerialize != null || property.GetIsSpecified != null;

					JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required, !optional);

					if (property.DefaultValue != null)
						propertySchema.Default = JToken.FromObject(property.DefaultValue);

					CurrentSchema.Properties.Add(property.PropertyName, propertySchema);
				}
			}

			if (type.IsSealed())
				CurrentSchema.AllowAdditionalProperties = false;
		}