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

			Type objectType = contract.UnderlyingType;

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

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

#if !(UNITY_IPHONE || UNITY_IOS || UNITY_WEBGL || UNITY_XBOXONE || UNITY_XBOX360 || UNITY_PS4 || UNITY_PS3 || UNITY_WII) || (UNITY_IOS || UNITY_WEBGL || UNITY_XBOXONE || UNITY_XBOX360 || UNITY_PS4 || UNITY_PS3 || UNITY_WII && !(UNITY_3_5 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3))
			foreach (KeyValuePair<JsonProperty, object> 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);
			}
#else
			propertyValues.ForEach(propertyValue => {
				ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, propertyValue.Key.UnderlyingName).Key;
				if (matchingConstructorParameter != null)
					constructorParameters[matchingConstructorParameter] = propertyValue.Value;
				else
					remainingPropertyValues.Add(propertyValue);
			});
#endif

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

			if (id != null)
				Serializer.ReferenceResolver.AddReference(this, id, createdObject);

			contract.InvokeOnDeserializing(createdObject, Serializer.Context);

#if !(UNITY_IPHONE || UNITY_IOS || UNITY_WEBGL || UNITY_XBOXONE || UNITY_XBOX360 || UNITY_PS4 || UNITY_PS3 || UNITY_WII) || (UNITY_IOS || UNITY_WEBGL || UNITY_XBOXONE || UNITY_XBOX360 || UNITY_PS4 || UNITY_PS3 || UNITY_WII && !(UNITY_3_5 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3))
			// 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(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 is JsonArrayContract)
					{
						JsonArrayContract propertyArrayContract = propertyContract as JsonArrayContract;

						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 is JsonDictionaryContract)
					{
						JsonDictionaryContract jsonDictionaryContract = propertyContract as JsonDictionaryContract;

						object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
						if (createdObjectDictionary != null)
						{
							IWrappedDictionary createdObjectDictionaryWrapper = jsonDictionaryContract.CreateWrapper(createdObjectDictionary);
							IWrappedDictionary newValues = jsonDictionaryContract.CreateWrapper(value);

							foreach (DictionaryEntry newValue in newValues)
							{
								createdObjectDictionaryWrapper.Add(newValue.Key, newValue.Value);
							}
						}
					}
				}
			}
#else
			// go through unused values and set the newly created object's properties
			remainingPropertyValues.ForEach(remainingPropertyValue => {
				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 is JsonArrayContract)
					{
						JsonArrayContract propertyArrayContract = propertyContract as JsonArrayContract;

						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 is JsonDictionaryContract)
					{
						JsonDictionaryContract jsonDictionaryContract = propertyContract as JsonDictionaryContract;

						object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
						if (createdObjectDictionary != null)
						{
							IWrappedDictionary createdObjectDictionaryWrapper = jsonDictionaryContract.CreateWrapper(createdObjectDictionary);
							IWrappedDictionary newValues = jsonDictionaryContract.CreateWrapper(value);

							foreach (DictionaryEntry newValue in newValues)
							{
								createdObjectDictionaryWrapper.Add(newValue.Key, newValue.Value);
							}
						}
					}
				}
			});
#endif


			contract.InvokeOnDeserialized(createdObject, Serializer.Context);
			return createdObject;
		}
		private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, string id)
		{
			contract.InvokeOnDeserializing(newObject, Serializer.Context);

			Dictionary<JsonProperty, PropertyPresence> propertiesPresence =
			  contract.Properties.ToDictionary(m => m, m => PropertyPresence.None);

			if (id != null)
				Serializer.ReferenceResolver.AddReference(this, id, newObject);

			int initialDepth = reader.Depth;

			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 (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
									throw new JsonSerializationException("Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType.Name));

								reader.Skip();
								continue;
							}

							if (!ReadForType(reader, property.PropertyType, property.Converter))
								throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));

							SetPropertyPresence(reader, property, propertiesPresence);

							SetPropertyValue(property, reader, newObject);
						}
						catch (Exception ex)
						{
							if (IsErrorHandled(newObject, contract, memberName, ex))
								HandleError(reader, initialDepth);
							else
								throw;
						}
						break;
					case JsonToken.EndObject:
						foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
						{
							JsonProperty property = propertyPresence.Key;
							PropertyPresence presence = propertyPresence.Value;

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

									if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Populate)
									  && property.Writable)
										property.ValueProvider.SetValue(newObject, EnsureType(property.DefaultValue, CultureInfo.InvariantCulture, property.PropertyType));
									break;
								case PropertyPresence.Null:
									if (property.Required == Required.Always)
										throw new JsonSerializationException("Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
									break;
							}
						}

						contract.InvokeOnDeserialized(newObject, Serializer.Context);
						return newObject;
					case JsonToken.Comment:
						// ignore
						break;
					default:
						throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType);
				}
			} while (reader.Read());

			throw new JsonSerializationException("Unexpected end when deserializing object.");
		}