public void ResolveReferences(ICollectionHandler handler, IJsonDict item) { deserializerState = new DeserializerStateInfo(); deserializerState.references = new Dictionary <object, IJsonDict>(); deserializerState.pending = new Stack <IEnumerable>(handler.GetContainers(item)); deserializerState.results = new Dictionary <IJsonDict, object>(); object referenceId = item.GetValueOrDefault("ref"); if (referenceId != null) { deserializerState.references[referenceId] = item; } IEnumerable enumerable; while (deserializerState.pending.Count > 0) { enumerable = deserializerState.pending.Pop(); // Debug.Log(string.Format("Processing queued item {0}", idgen.GetId(enumerable, out dummy))); var list = enumerable as IJsonList; if (list != null) { for (int index = 0; index < list.Count; ++index) { if ((item = list[index] as IJsonDict) == null) { continue; // Not an object } if ((item = ResolveItem(item)) == null) { continue; // Replacement not needed } list[index] = item; } continue; } var dict = enumerable as IJsonDict; if (dict != null) { foreach (JsonKey kvp in dict) { if ((item = kvp.Value as IJsonDict) == null) { continue; // Not an object } if ((item = ResolveItem(item)) == null) { continue; // Replacement not needed. } dict[kvp.Key] = item; } continue; } throw new SerializationException(string.Format("Unexpected enumerable of type {0}", enumerable.GetType().FullName)); } }
public override Direction Deserialize(IJsonDict source) { EnsureValueIsType <string>(source, "from", false, true); string directionType = (string)source.GetValueOrDefault("from", null); int numElements = 0; switch (directionType) { case null: break; case "quaternion": numElements = 4; break; case "euler": case "vector": numElements = 3; break; default: throw new SerializationException(string.Format("{0} object: 'from' must be one of (\"quaternioun\", \"euler\", \"vector\", or null).", info.Name)); } var elements = GetElements(source, numElements); switch (elements.Count) { case 3: // From Euler angles (default) or vector (explicit) return(new Direction(new Vector3d(elements[0], elements[1], elements[2]), directionType != "vector")); case 4: // Quaternion return(new Direction(new QuaternionD(elements[0], elements[1], elements[2], elements[3]))); default: throw new SerializationException(string.Format("{0} object: data field must contain exactly 3 or 4 elements.", info.Name)); } }
public override Lexicon Deserialize(IJsonDict source) { Validate(source); bool caseSensitive = (bool)source.GetValueOrDefault("sensitive", false); var data = (IJsonDict)source["data"]; var keys = (IJsonList)source["keys"]; var values = (IJsonList)source["values"]; if (keys.Count != values.Count) { throw new SerializationException("Dict must have the same number of values as it has keys."); } var output = new Lexicon(); output.SetSuffix("CASESENSITIVE", caseSensitive); serializer.deserializerState.results[source] = output; data.Select(kvp => output[(Structure)serializer.Deserialize(kvp.Key)] = (Structure)serializer.Deserialize(kvp.Value)); foreach (var kvp in data.Select(x => new KeyValuePair <Structure, Structure>((Structure)serializer.Deserialize(x.Key), (Structure)serializer.Deserialize(x.Value)))) { output[kvp.Key] = kvp.Value; } return(output); }
/// <summary> /// Helper function for resolving references. Updates the passed list of references. Returns a non-null value if the parent container should replace /// its current item with the returned item. /// </summary> /// <param name="references"></param> /// <param name="item"></param> /// <returns></returns> internal IJsonDict ResolveItem(IJsonDict item) { object typeId = GetTypeIdentifier(item); object objectId = item.GetValueOrDefault("ref"); // Debug.Log(string.Format("Identified object of type {0} -- object ID: {1}", typeId, objectId)); IJsonDict referenced = (objectId == null) ? null : deserializerState.references.GetValueOrDefault(objectId); if (typeId as string == "ref") // Found a reference { if (objectId == null) { throw new SerializationException("Found a missing or null reference ID."); } // This works because we don't want to replace if the item didn't exist (and thus would return NULL), // and we do want to replace if it did (and thus would return an actual value) if (referenced == null) { // Debug.Log(string.Format("Adding new pending reference to {0}", objectId)); deserializerState.references[objectId] = item; } else { // Debug.Log(string.Format("Replacing reference with actual object of type ", referenced["type"])); } return(referenced); } // Still here? Okay. // Nested container check. TypeHandler handler = registry.GetDeserializer(typeId).CreateHandler(this); if (handler is ICollectionHandler) { // FIXME: See if this code is actually needed. if (item.ContainsKey("_visited")) { Debug.LogWarning("*** WARNING ***: Container already visited."); } else { item["_visited"] = true; foreach (var container in ((ICollectionHandler)handler).GetContainers(item)) { deserializerState.pending.Push(container); } } } if (objectId == null) { return(null); // Unreferenced object, nothing to do. } if (referenced == null) { deserializerState.references[objectId] = item; // Debug.Log("Saving reference."); } else { // Already references something else. Let's hope it's a reference. if (GetTypeIdentifier(referenced) as string != "ref") { // ... nope. Complain loudly. throw new SerializationException(string.Format("Object reference '{0}' refers to multiple non-reference objects", objectId)); } // Everything we've previously seen up until now points to the old object. It's way too much of a hassle to replace it, so... // instead we clear it and copy all of our data to it. // Debug.Log(string.Format("Copying over to actual object of type ", referenced["type"])); referenced.Clear(); foreach (JsonKey kvp in item) { referenced[kvp.Key] = kvp.Value; // Resistance is futile. You will be assimilated. } // Debug.Log("Done copying over"); } return(referenced); }