private Base Dict2Base(Dictionary <string, object> dictObj) { String typeName = dictObj[TypeDiscriminator] as String; Type type = SerializationUtilities.GetType(typeName); Base baseObj = Activator.CreateInstance(type) as Base; dictObj.Remove(TypeDiscriminator); dictObj.Remove("__closure"); Dictionary <string, PropertyInfo> staticProperties = SerializationUtilities.GetTypePropeties(typeName); List <MethodInfo> onDeserializedCallbacks = SerializationUtilities.GetOnDeserializedCallbacks(typeName); foreach (KeyValuePair <string, object> entry in dictObj) { string lowerPropertyName = entry.Key.ToLower(); if (staticProperties.ContainsKey(lowerPropertyName) && staticProperties[lowerPropertyName].CanWrite) { PropertyInfo property = staticProperties[lowerPropertyName]; if (entry.Value == null) { // Check for JsonProperty(NullValueHandling = NullValueHandling.Ignore) attribute JsonPropertyAttribute attr = property.GetCustomAttribute <JsonPropertyAttribute>(true); if (attr != null && attr.NullValueHandling == NullValueHandling.Ignore) { continue; } } Type targetValueType = property.PropertyType; object convertedValue; bool conversionOk = ValueConverter.ConvertValue(targetValueType, entry.Value, out convertedValue); if (conversionOk) { property.SetValue(baseObj, convertedValue); } else { // Cannot convert the value in the json to the static property type throw new Exception(String.Format("Cannot deserialize {0} to {1}", entry.Value.GetType().FullName, targetValueType.FullName)); } } else { // No writable property with this name CallSiteCache.SetValue(entry.Key, baseObj, entry.Value); } } foreach (MethodInfo onDeserialized in onDeserializedCallbacks) { onDeserialized.Invoke(baseObj, new object[] { null }); } return(baseObj); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } if (reader.TokenType == JsonToken.Null) { return(null); } // Check if we passed in an array, rather than an object. // TODO: Test the following branch. It's not used anywhere at the moment, and the default serializer prevents it from // ever being used (only allows single object serialization) if (reader.TokenType == JsonToken.StartArray) { var list = new List <Base>(); var jarr = JArray.Load(reader); foreach (var val in jarr) { if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } var whatever = SerializationUtilities.HandleValue(val, serializer, CancellationToken); list.Add(whatever as Base); } return(list); } if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } var jObject = JObject.Load(reader); if (jObject == null) { return(null); } var objType = jObject.GetValue(TypeDiscriminator); // Assume dictionary! if (objType == null) { var dict = new Dictionary <string, object>(); foreach (var val in jObject) { if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } dict[val.Key] = SerializationUtilities.HandleValue(val.Value, serializer, CancellationToken); } return(dict); } if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } var discriminator = Extensions.Value <string>(objType); // Check for references. if (discriminator == "reference") { var id = Extensions.Value <string>(jObject.GetValue("referencedId")); string str = ""; if (ReadTransport != null) { str = ReadTransport.GetObject(id); } else { Log.CaptureAndThrow(new SpeckleException("Cannot resolve reference, no transport is defined."), level: Sentry.Protocol.SentryLevel.Warning); } if (str != null && str != "") { jObject = JObject.Parse(str); discriminator = Extensions.Value <string>(jObject.GetValue(TypeDiscriminator)); } else { Log.CaptureAndThrow(new SpeckleException("Cannot resolve reference. The provided transport could not find it."), level: Sentry.Protocol.SentryLevel.Warning); } } var type = SerializationUtilities.GetType(discriminator); var obj = existingValue ?? Activator.CreateInstance(type); var contract = (JsonDynamicContract)serializer.ContractResolver.ResolveContract(type); var used = new HashSet <string>(); // remove unsettable properties jObject.Remove(TypeDiscriminator); jObject.Remove("__closure"); if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } foreach (var jProperty in jObject.Properties()) { if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } if (used.Contains(jProperty.Name)) { continue; } used.Add(jProperty.Name); // first attempt to find a settable property, otherwise fall back to a dynamic set without type JsonProperty property = contract.Properties.GetClosestMatchProperty(jProperty.Name); if (property != null && property.Writable && !property.Ignored) { if (type == typeof(Abstract) && property.PropertyName == "base") { var propertyValue = SerializationUtilities.HandleAbstractOriginalValue(jProperty.Value, ((JValue)jObject.GetValue("assemblyQualifiedName")).Value as string, serializer); property.ValueProvider.SetValue(obj, propertyValue); } else { var val = SerializationUtilities.HandleValue(jProperty.Value, serializer, CancellationToken, property); property.ValueProvider.SetValue(obj, val); } } else { // dynamic properties CallSiteCache.SetValue(jProperty.Name, obj, SerializationUtilities.HandleValue(jProperty.Value, serializer, CancellationToken)); } } if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } TotalProcessedCount++; OnProgressAction?.Invoke("DS", 1); foreach (var callback in contract.OnDeserializedCallbacks) { callback(obj, serializer.Context); } return(obj); }