private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, string id) { contract.InvokeOnDeserializing(newObject); Dictionary <string, bool> requiredProperties = contract.Properties.Where(m => m.Required).ToDictionary(m => m.PropertyName, m => false); if (id != null) { _serializer.ReferenceResolver.AddReference(id, newObject); } do { 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)); } if (reader.TokenType != JsonToken.Null) { SetRequiredProperty(memberName, requiredProperties); } SetObjectMember(reader, newObject, contract, memberName); break; case JsonToken.EndObject: foreach (KeyValuePair <string, bool> requiredProperty in requiredProperties) { if (!requiredProperty.Value) { throw new JsonSerializationException("Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, requiredProperty.Key)); } } contract.InvokeOnDeserialized(newObject); return(newObject); case JsonToken.Comment: // ignore break; default: throw new JsonSerializationException("Unexpected token when deserializing object: " + reader.TokenType); } } while (reader.Read()); throw new JsonSerializationException("Unexpected end when deserializing object."); }
private object CreateObjectFromNonDefaultConstructor(JsonObjectContract contract, JsonReader reader) { Type objectType = contract.UnderlyingType; // 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 IDictionary <JsonProperty, object> propertyValues = contract.Properties.Where(p => !p.Ignored).ToDictionary(kv => kv, kv => (object)null); bool exit = false; do { 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)); } JsonProperty property; // attempt exact case match first // then try match ignoring case if (contract.Properties.TryGetClosestMatchProperty(memberName, out property)) { if (!property.Ignored) { Type memberType = ReflectionUtils.GetMemberUnderlyingType(property.Member); propertyValues[property] = CreateValue(reader, memberType, null, property.MemberConverter); } } else { if (_serializer.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); } } while (!exit && reader.Read()); IDictionary <ParameterInfo, object> constructorParameters = c.GetParameters().ToDictionary(p => p, p => (object)null); IDictionary <JsonProperty, object> remainingPropertyValues = new Dictionary <JsonProperty, object>(); foreach (KeyValuePair <JsonProperty, object> propertyValue in propertyValues) { ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, propertyValue.Key.PropertyName).Key; if (matchingConstructorParameter != null) { constructorParameters[matchingConstructorParameter] = propertyValue.Value; } else { remainingPropertyValues.Add(propertyValue); } } object createdObject = ReflectionUtils.CreateInstance(objectType, constructorParameters.Values.ToArray()); contract.InvokeOnDeserializing(createdObject); // go through unused values and set the newly created object's properties foreach (KeyValuePair <JsonProperty, object> remainingPropertyValue in remainingPropertyValues) { if (ShouldSetPropertyValue(remainingPropertyValue.Key, remainingPropertyValue.Value)) { ReflectionUtils.SetMemberValue(remainingPropertyValue.Key.Member, createdObject, remainingPropertyValue.Value); } } contract.InvokeOnDeserialized(createdObject); return(createdObject); }