private void EndObject (object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, Dictionary<JsonProperty, PropertyPresence> propertiesPresence)
		{
			if (propertiesPresence != null) {
				foreach (KeyValuePair<JsonProperty, PropertyPresence> 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.Ignored)
									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();

						if (CheckPropertyName(reader, memberName))
							continue;

						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, member, 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, member, 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;
		}
		private void SetExtensionData (JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o)
		{
			if (contract.ExtensionDataSetter != null) {
				try {
					object value = CreateValueInternal(reader, null, null, null, contract, member, null);

					contract.ExtensionDataSetter(o, memberName, value);
				}
				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();
			}
		}
		public object CreateNewObject (JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultCreator)
		{
			object newObject = null;

			if (objectContract.OverrideCreator != null) {
				if (objectContract.CreatorParameters.Count > 0) {
					createdFromNonDefaultCreator = true;
					return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id);
				}

				newObject = objectContract.OverrideCreator(new object[0]);
			}
			else if (objectContract.DefaultCreator != null &&
			                  (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedCreator == 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 creator
				newObject = objectContract.DefaultCreator();
			}
			else if (objectContract.ParametrizedCreator != null) {
				createdFromNonDefaultCreator = true;
				return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParametrizedCreator, id);
			}

			if (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));
                
				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));
			}

			createdFromNonDefaultCreator = false;
			return newObject;
		}
		private IDictionary<JsonProperty, object> ResolvePropertyAndCreatorValues (JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType, out IDictionary<string, object> extensionData)
		{
			extensionData = (contract.ExtensionDataSetter != null) ? new Dictionary<string, object>() : null;

			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.CreatorParameters.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;
							continue;
						}
					}
					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));
					}

					if (extensionData != null) {
						object value = CreateValueInternal(reader, null, null, null, contract, containerProperty, null);
						extensionData[memberName] = value;
					}
					else {
						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 CreateObjectUsingCreatorWithParameters (JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor<object> creator, string id)
		{
			ValidationUtils.ArgumentNotNull(creator, "creator");

			// 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;

			Type objectType = contract.UnderlyingType;

			if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) {
				string parameters = string.Join(", ", contract.CreatorParameters.Select(p => p.PropertyName).ToArray());
				TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, parameters)), null);
			}

			IDictionary<string, object> extensionData;
			IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, objectType, out extensionData);

			object[] creatorParameterValues = new object[contract.CreatorParameters.Count];
			IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();

			foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues) {
				JsonProperty property = propertyValue.Key;

				JsonProperty matchingCreatorParameter;
				if (contract.CreatorParameters.Contains(property)) {
					matchingCreatorParameter = property;
				}
				else {
					// check to see if a parameter with the same name as the underlying property name exists and match to that
					matchingCreatorParameter = contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName, property.UnderlyingName);
				}

				if (matchingCreatorParameter != null) {
					int i = contract.CreatorParameters.IndexOf(matchingCreatorParameter);
					creatorParameterValues[i] = propertyValue.Value;
				}
				else {
					remainingPropertyValues.Add(propertyValue);
				}

				if (propertiesPresence != null) {
					// map from creator property to normal property
					JsonProperty presenceProperty = propertiesPresence.Keys.FirstOrDefault(p => p.PropertyName == property.PropertyName);
					if (presenceProperty != null)
						propertiesPresence[presenceProperty] = (propertyValue.Value == null) ? PropertyPresence.Null : PropertyPresence.Value;
				}
			}

			object createdObject = creator(creatorParameterValues);

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

			OnDeserializing(reader, contract, createdObject);

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

				if (ShouldSetPropertyValue(property, 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) {
						JsonArrayContract propertyArrayContract = (JsonArrayContract)propertyContract;

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

							foreach (object newValue in newValues) {
								createdObjectCollectionWrapper.Add(newValue);
							}
						}
					}
					else if (propertyContract.ContractType == JsonContractType.Dictionary) {
						JsonDictionaryContract 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);
							}
						}
					}
				}
			}

			if (extensionData != null) {
				foreach (KeyValuePair<string, object> e in extensionData) {
					contract.ExtensionDataSetter(createdObject, e.Key, e.Value);
				}
			}

			EndObject(createdObject, reader, contract, reader.Depth, propertiesPresence);

			OnDeserialized(reader, contract, createdObject);
			return createdObject;
		}
        private void GenerateObjectSchema(Type type, JsonObjectContract contract)
        {
            CurrentSchema.Properties = new Dictionary<string, JsonSchema>();
            foreach (JsonProperty 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;
        }
        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;
                }
            }

            if (contract.ExtensionDataGetter != null)
            {
                IEnumerable<KeyValuePair<object, object>> extensionData = contract.ExtensionDataGetter(value);
                if (extensionData != null)
                {
                    foreach (KeyValuePair<object, object> e in extensionData)
                    {
                        JsonContract keyContract = GetContractSafe(e.Key);
                        JsonContract valueContract = GetContractSafe(e.Value);

                        bool escape;
                        string propertyName = GetPropertyName(writer, e.Key, keyContract, out escape);

                        if (ShouldWriteReference(e.Value, null, valueContract, contract, member))
                        {
                            writer.WritePropertyName(propertyName);
                            WriteReference(writer, e.Value);
                        }
                        else
                        {
                            if (!CheckForCircularReference(writer, e.Value, null, valueContract, contract, member))
                                continue;

                            writer.WritePropertyName(propertyName);

                            SerializeValue(writer, e.Value, valueContract, null, contract, member);
                        }
                    }
                }
            }

            writer.WriteEndObject();

            _serializeStack.RemoveAt(_serializeStack.Count - 1);

            OnSerialized(writer, contract, value);
        }