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