private object PopulateObject(object newObject, JsonReader reader, Type objectType) { while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string memberName = reader.Value.ToString(); SetObjectMember(reader, newObject, objectType, memberName); break; case JsonToken.EndObject: return newObject; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } throw new JsonSerializationException("Unexpected end when deserializing object."); }
private object CreateAndPopulateObject(JsonReader reader, Type objectType) { object newObject; if (ReflectionUtils.HasDefaultConstructor(objectType)) { newObject = Activator.CreateInstance(objectType); PopulateObject(newObject, reader, objectType); return newObject; } else { 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 IDictionary<ParameterInfo, object> constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null); MemberMappingCollection mappings = GetMemberMappings(objectType); 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)); ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, memberName).Key; MemberMapping mapping; if (matchingConstructorParameter != null && mappings.TryGetMapping(memberName, out mapping) && !mapping.Ignored) { constructorParameters[matchingConstructorParameter] = CreateObject(reader, matchingConstructorParameter.ParameterType, null, mapping.MemberConverter); } else { // skip token and all child tokens reader.Skip(); } break; case JsonToken.EndObject: exit = true; break; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } newObject = ReflectionUtils.CreateInstance(objectType, constructorParameters.Values.ToArray()); return newObject; } }
private IList PopulateList(IList list, Type listItemType, JsonReader reader) { while (reader.Read()) { switch (reader.TokenType) { case JsonToken.EndArray: return list; case JsonToken.Comment: break; default: object value = CreateObject(reader, listItemType, null, null); list.Add(value); break; } } throw new JsonSerializationException("Unexpected end when deserializing array."); }
private IDictionary PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader) { Type dictionaryType = dictionary.UnderlyingDictionary.GetType(); Type dictionaryKeyType = ReflectionUtils.GetDictionaryKeyType(dictionaryType); Type dictionaryValueType = ReflectionUtils.GetDictionaryValueType(dictionaryType); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: object keyValue = EnsureType(reader.Value, dictionaryKeyType); reader.Read(); dictionary.Add(keyValue, CreateObject(reader, dictionaryValueType, null, null)); break; case JsonToken.EndObject: return dictionary; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } throw new JsonSerializationException("Unexpected end when deserializing object."); }
private void SetObjectMember(JsonReader reader, object target, Type targetType, string memberName) { if (!reader.Read()) throw new JsonSerializationException("Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); MemberMappingCollection memberMappings = GetMemberMappings(targetType); Type memberType; object value; // test if a member with memberName exists on the type // otherwise test if target is a dictionary and assign value with the key if it is if (memberMappings.Contains(memberName)) { MemberMapping memberMapping = memberMappings[memberName]; if (memberMapping.Ignored) { reader.Skip(); return; } // get the member's underlying 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; } value = CreateObject(reader, memberType, (useExistingValue) ? currentValue : null, GetConverter(memberMapping.Member, memberType)); if (_nullValueHandling == NullValueHandling.Ignore && value == null) return; if (_defaultValueHandling == DefaultValueHandling.Ignore && object.Equals(value, memberMapping.DefaultValue)) return; if (!useExistingValue) ReflectionUtils.SetMemberValue(memberMapping.Member, target, value); } else { if (_missingMemberHandling == MissingMemberHandling.Error) throw new JsonSerializationException("Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, targetType.GetType().Name)); } }
/// <summary> /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/> /// into an instance of the specified type. /// </summary> /// <param name="reader">The <see cref="JsonReader"/> containing the object.</param> /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param> /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns> public object Deserialize(JsonReader reader, Type objectType) { if (reader == null) throw new ArgumentNullException("reader"); if (!reader.Read()) return null; if (objectType != null) return CreateObject(reader, objectType, null, null); else return CreateJToken(reader); }