private void SetMappingValue(JsonMemberMapping memberMapping, JsonReader reader, object target) { if (memberMapping.Ignored) { reader.Skip(); return; } // get the member's underlying type Type memberType = ReflectionUtils.GetMemberUnderlyingType(memberMapping.Member); object currentValue = null; bool useExistingValue = false; if ((_objectCreationHandling == ObjectCreationHandling.Auto || _objectCreationHandling == ObjectCreationHandling.Reuse) && (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)) { currentValue = ReflectionUtils.GetMemberValue(memberMapping.Member, target); useExistingValue = (currentValue != null && !memberType.IsArray && !ReflectionUtils.InheritsGenericDefinition(memberType, typeof(ReadOnlyCollection<>))); } if (!memberMapping.Writable && !useExistingValue) { reader.Skip(); return; } object value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null, JsonTypeReflector.GetConverter(memberMapping.Member, memberType)); if (!useExistingValue && ShouldSetMappingValue(memberMapping, value)) ReflectionUtils.SetMemberValue(memberMapping.Member, target, value); }
private object CreateObjectFromNonDefaultConstructor(Type objectType, JsonReader reader) { // object should have a single constructor ConstructorInfo c = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).SingleOrDefault(); if (c == null) throw new JsonSerializationException("Could not find a public constructor for type {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); // create a dictionary to put retrieved values into JsonMemberMappingCollection memberMappings = GetMemberMappings(objectType); IDictionary<JsonMemberMapping, object> mappingValues = memberMappings.ToDictionary(kv => kv, kv => (object)null); bool exit = false; while (!exit && reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string memberName = reader.Value.ToString(); if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); JsonMemberMapping memberMapping; // attempt exact case match first // then try match ignoring case if (memberMappings.TryGetClosestMatchMapping(memberName, out memberMapping)) { if (!memberMapping.Ignored) { Type memberType = ReflectionUtils.GetMemberUnderlyingType(memberMapping.Member); mappingValues[memberMapping] = CreateObject(reader, memberType, null, memberMapping.MemberConverter); } } else { if (_missingMemberHandling == MissingMemberHandling.Error) throw new JsonSerializationException("Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, objectType.Name)); reader.Skip(); } break; case JsonToken.EndObject: exit = true; break; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } IDictionary<ParameterInfo, object> constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null); IDictionary<JsonMemberMapping, object> remainingMappingValues = new Dictionary<JsonMemberMapping, object>(); foreach (KeyValuePair<JsonMemberMapping, object> mappingValue in mappingValues) { ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, mappingValue.Key.MappingName).Key; if (matchingConstructorParameter != null) constructorParameters[matchingConstructorParameter] = mappingValue.Value; else remainingMappingValues.Add(mappingValue); } object createdObject = ReflectionUtils.CreateInstance(objectType, constructorParameters.Values.ToArray()); // go through unused values and set the newly created object's properties foreach (KeyValuePair<JsonMemberMapping, object> remainingMappingValue in remainingMappingValues) { if (ShouldSetMappingValue(remainingMappingValue.Key, remainingMappingValue.Value)) ReflectionUtils.SetMemberValue(remainingMappingValue.Key.Member, createdObject, remainingMappingValue.Value); } return createdObject; }
private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName) { JsonMemberMappingCollection memberMappings = GetMemberMappings(targetType); JsonMemberMapping memberMapping; // attempt exact case match first // then try match ignoring case if (memberMappings.TryGetClosestMatchMapping(memberName, out memberMapping)) { SetMappingValue(memberMapping, reader, target); } else { if (_missingMemberHandling == MissingMemberHandling.Error) throw new JsonSerializationException("Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, targetType.Name)); reader.Skip(); } }