public Base Deserialize(String rootObjectJson) { if (Busy) { throw new Exception("A deserializer instance can deserialize only 1 object at a time. Consider creating multiple deserializer instances"); } try { Busy = true; DeserializedObjects = new Dictionary <string, object>(); WorkerThreads = new DeserializationWorkerThreads(this); WorkerThreads.Start(); List <(string, int)> closures = GetClosures(rootObjectJson); closures.Sort((a, b) => b.Item2.CompareTo(a.Item2)); foreach (var closure in closures) { string objId = closure.Item1; string objJson = ReadTransport.GetObject(objId); object deserializedOrPromise = DeserializeTransportObjectProxy(objJson); lock (DeserializedObjects) { DeserializedObjects[objId] = deserializedOrPromise; } } object ret = DeserializeTransportObject(rootObjectJson); return(ret as Base); } finally { DeserializedObjects = null; WorkerThreads.Dispose(); WorkerThreads = null; Busy = false; } }
public object ConvertJsonElement(JToken doc) { if (CancellationToken.IsCancellationRequested) { return(null); // Check for cancellation } switch (doc.Type) { case JTokenType.Undefined: case JTokenType.Null: case JTokenType.None: return(null); case JTokenType.Boolean: return((bool)doc); case JTokenType.Integer: return((long)doc); case JTokenType.Float: return((double)doc); case JTokenType.String: return((string)doc); case JTokenType.Date: return((DateTime)doc); case JTokenType.Array: JArray docAsArray = (JArray)doc; List <object> jsonList = new List <object>(docAsArray.Count); int retListCount = 0; foreach (JToken value in docAsArray) { object convertedValue = ConvertJsonElement(value); retListCount += (convertedValue is DataChunk) ? ((DataChunk)convertedValue).data.Count : 1; jsonList.Add(convertedValue); } List <object> retList = new List <object>(retListCount); foreach (object jsonObj in jsonList) { if (jsonObj is DataChunk) { retList.AddRange(((DataChunk)jsonObj).data); } else { retList.Add(jsonObj); } } return(retList); case JTokenType.Object: Dictionary <string, object> dict = new Dictionary <string, object>(); foreach (JToken propJToken in doc) { JProperty prop = (JProperty)propJToken; if (prop.Name == "__closure") { continue; } dict[prop.Name] = ConvertJsonElement(prop.Value); } if (!dict.ContainsKey(TypeDiscriminator)) { return(dict); } if ((dict[TypeDiscriminator] as String) == "reference" && dict.ContainsKey("referencedId")) { string objId = dict["referencedId"] as String; object deserialized = null; lock (DeserializedObjects) { if (DeserializedObjects.ContainsKey(objId)) { deserialized = DeserializedObjects[objId]; } } if (deserialized != null && deserialized is Task <object> ) { deserialized = ((Task <object>)deserialized).Result; lock (DeserializedObjects) { DeserializedObjects[objId] = deserialized; } } if (deserialized != null) { return(deserialized); } // This reference was not already deserialized. Do it now in sync mode string objectJson = ReadTransport.GetObject(objId); deserialized = DeserializeTransportObject(objectJson); lock (DeserializedObjects) { DeserializedObjects[objId] = deserialized; } return(deserialized); } return(Dict2Base(dict)); default: throw new Exception("Json value not supported: " + doc.Type.ToString()); } }
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); }