public object Serialize(object input) { // If Unity supported a modern C# version with, say, dynamic, we could go back to the overloaded methods approach // Instead of this giant mess of if-checks if (input is PrimitiveStructure) { return(((PrimitiveStructure)input).ToPrimitive()); } ICollectionHandler referenced = serializerState.references.GetValueOrDefault(input); if (referenced != null) { return(MakeReference(referenced)); } TypeHandler handler = registry.GetSerializer(input).CreateHandler(this); // Will throw on unsupported types. if (handler is ICollectionHandler) { // It's important that the reference is set up BEFORE we serialize the handler, otherwise a nested reference to the input may fail to notice // the existing reference since we haven't created it yet. serializerState.references[input] = (ICollectionHandler)handler; } return(handler.ProxySerialize(input)); }
/// <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); }