public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //we may be starting the deserialization here, if thats the case we need to resolve this object as the root object obj; if (DocumentRootConverter.TryResolveAsRootData(reader, objectType, serializer, out obj)) { return(obj); } //read into the 'Data' element return(ReaderUtil.ReadInto( reader as ForkableJsonReader ?? new ForkableJsonReader(reader), DataReadPathRegex, dataReader => { //if the value has been explicitly set to null then the value of the element is simply null if (dataReader.TokenType == JsonToken.Null) { return null; } JsonObjectContract contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType); var serializationData = SerializationData.GetSerializationData(dataReader); //if we arent given an existing value check the references to see if we have one in there //if we dont have one there then create a new object to populate if (existingValue == null) { var reference = ReaderUtil.ReadAheadToIdentifyObject(dataReader); if (!serializationData.Included.TryGetValue(reference, out existingValue)) { existingValue = contract.DefaultCreator(); serializationData.Included.Add(reference, existingValue); } if (existingValue is JObject) { //sometimes the value in the reference resolver is a JObject. This occurs when we //did not know what type it should be when we first read it (i.e. included was processed //before the item). In these cases we will create a new object and read data from the JObject dataReader = new ForkableJsonReader(((JObject)existingValue).CreateReader(), dataReader.SerializationDataToken); dataReader.Read(); //JObject readers begin at Not Started existingValue = contract.DefaultCreator(); serializationData.Included[reference] = existingValue; } } PopulateProperties(serializer, existingValue, dataReader, contract); return existingValue; })); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //we may be starting the deserialization here, if thats the case we need to resolve this object as the root object obj; if (DocumentRootConverter.TryResolveAsRootData(reader, objectType, serializer, out obj)) { return(obj); } JsonObjectContract contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType); var isNew = false; if (existingValue == null) { existingValue = contract.DefaultCreator(); isNew = true; } existingValue = PopulateProperties(serializer, existingValue, reader, contract); if (isNew) { var id = contract.Properties.GetClosestMatchProperty(PropertyNames.Id).ValueProvider.GetValue(existingValue); var type = existingValue.GetType().Name.ToLower(); var typeProp = contract.Properties.GetClosestMatchProperty(PropertyNames.Type); if (typeProp != null) { type = typeProp.ValueProvider.GetValue(existingValue).ToString(); } serializer.ReferenceResolver.AddReference(null, type + ":" + id, existingValue); } return(existingValue); }
private object ReadObject(JsonReader reader, JsonObjectContract objectContract, JsonSerializer serializer) { var token = (JObject)JToken.ReadFrom(reader); var objectType = objectContract.UnderlyingType; if (IsTypeExplicitlyDefined(token, serializer.SerializationBinder, ref objectType)) { reader = token.CreateReader(); return(ReadJson(reader, objectType, null, serializer)); } else { if (objectContract.UnderlyingType.IsAbstract) { throw new InvalidOperationException(); } if (entityCache.GetEntity(token, objectContract.UnderlyingType, out var id) is object value) { serializer.Populate(token.CreateReader(), value); return(value); } if (objectContract.OverrideCreator is not null) { throw new NotImplementedException(); } else if (objectContract.DefaultCreator is not null) { value = objectContract.DefaultCreator(); serializer.Populate(token.CreateReader(), value); } else { throw new NotImplementedException(); } if (id is not null) { entityCache.PutEntity(id, value); } return(value); } }
public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultCreator) { object newObject = null; if (objectContract.OverrideCreator != null) { if (objectContract.CreatorParameters.Count > 0) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id); } newObject = objectContract.OverrideCreator(new object[0]); } else if (objectContract.DefaultCreator != null && (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedCreator == null)) { // use the default constructor if it is... // public // non-public and the user has change constructor handling settings // non-public and there is no other creator newObject = objectContract.DefaultCreator(); } else if (objectContract.ParametrizedCreator != null) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParametrizedCreator, id); } if (newObject == null) { if (!objectContract.IsInstantiable) throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); } createdFromNonDefaultCreator = false; return newObject; }
private object CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, string id) { object newObject = null; if (contract.UnderlyingType.IsInterface || contract.UnderlyingType.IsAbstract) throw new JsonSerializationException("Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer.ConstructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { newObject = contract.DefaultCreator(); } if (newObject != null) { PopulateObject(newObject, reader, contract, id); return newObject; } return CreateObjectFromNonDefaultConstructor(reader, contract, id); }