private void SetPropertyValue(JsonProperty property, JsonReader reader, object target)
		{
			if (property.Ignored)
			{
				reader.Skip();
				return;
			}

			object currentValue = null;
			bool useExistingValue = false;
			bool gottenCurrentValue = false;

			ObjectCreationHandling objectCreationHandling =
			  property.ObjectCreationHandling.GetValueOrDefault(Serializer.ObjectCreationHandling);

			if ((objectCreationHandling == ObjectCreationHandling.Auto || objectCreationHandling == ObjectCreationHandling.Reuse)
			  && (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)
			  && property.Readable)
			{
				currentValue = property.ValueProvider.GetValue(target);
				gottenCurrentValue = true;

				useExistingValue = (currentValue != null
				  && !property.PropertyType.IsArray
					&& !ReflectionUtils.InheritsGenericDefinition(property.PropertyType, typeof(ReadOnlyCollection<>))
					  && !property.PropertyType.IsValueType);
			}

			if (!property.Writable && !useExistingValue)
			{
				reader.Skip();
				return;
			}

			// test tokentype here because null might not be convertable to some types, e.g. ignoring null when applied to DateTime
			if (property.NullValueHandling.GetValueOrDefault(Serializer.NullValueHandling) == NullValueHandling.Ignore && reader.TokenType == JsonToken.Null)
			{
				reader.Skip();
				return;
			}

			// test tokentype here because default value might not be convertable to actual type, e.g. default of "" for DateTime
			if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Ignore)
			  && JsonReader.IsPrimitiveToken(reader.TokenType)
				&& MiscellaneousUtils.ValueEquals(reader.Value, property.DefaultValue))
			{
				reader.Skip();
				return;
			}

			object existingValue = (useExistingValue) ? currentValue : null;
			object value = CreateValueProperty(reader, property, target, gottenCurrentValue, existingValue);

			// 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)
					property.SetIsSpecified(target, true);
			}
		}
    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;
    }