private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target)
		{
			object currentValue;
			bool useExistingValue;
			JsonContract propertyContract;
			bool gottenCurrentValue;

			if (CalculatePropertyDetails(property, ref propertyConverter, containerContract, containerProperty, reader, target, out useExistingValue, out currentValue, out propertyContract, out gottenCurrentValue))
				return false;

			object value;

			if (propertyConverter != null && propertyConverter.CanRead)
			{
				if (!gottenCurrentValue && target != null && property.Readable)
					currentValue = property.ValueProvider.GetValue(target);

				value = DeserializeConvertable(propertyConverter, reader, property.PropertyType, currentValue);
			}
			else
			{
				value = CreateValueInternal(reader, property.PropertyType, propertyContract, property, containerContract, containerProperty, (useExistingValue) ? currentValue : null);
			}

			// always set the value if useExistingValue is false,
			// otherwise also set it if CreateValue returns a new value compared to the currentValue
			// this could happen because of a JsonConverter against the type
			if ((!useExistingValue || value != currentValue) && ShouldSetPropertyValue(property, value))
			{
				property.ValueProvider.SetValue(target, value);

				if (property.SetIsSpecified != null)
				{
					if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
						TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "IsSpecified for property '{0}' on {1} set to true.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null);

					property.SetIsSpecified(target, true);
				}

				return true;
			}

			// the value wasn't set be JSON was populated onto the existing value
			return useExistingValue;
		}