protected void Validate(IJsonDict source) { EnsureValueIsType <IJsonDict>(source, "data"); EnsureValueIsType <IJsonList>(source, "keys"); EnsureValueIsType <IJsonList>(source, "values"); EnsureValueIsType <Boolean>(source, "sensitive", mustExist: false); }
public void Import(IJsonDict source) { foreach (JsonKey kvp in source) { this[kvp.Key] = kvp.Value; } }
public override IEnumerable <IEnumerable> GetContainers(IJsonDict source) { EnsureValueIsType <IJsonList>(source); return(new List <IEnumerable> { (IJsonList)source["data"] }); }
public override BodyTarget Deserialize(IJsonDict source) { EnsureValueIsType <int>(source); int bodyId = (int)source["data"]; return(BodyTarget.CreateOrGetExisting(GetBodyById(bodyId), serializer.SharedObjects)); }
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)); } }
/// <summary> /// Returns the object type identifier from the specified JSON Dict. Raises an exception if no type identifier is specified. /// </summary> /// <param name="input"></param> protected object GetTypeIdentifier(IJsonDict input) { try { return(input["type"]); } catch (KeyNotFoundException) { throw new SerializationException("Object type not declared."); } }
public override TCollection Deserialize(IJsonDict source) { EnsureValueIsType <IJsonList>(source); TCollection result = (TCollection)Factory.Invoke(new object[0]); serializer.deserializerState.results[source] = result; AddItems( result, ((IJsonList)source["data"]).Cast <object>().Select(element => (TItem)(serializer.Deserialize(element))) ); return(result); }
public object Deserialize(object input) { if (input == null) { throw new SerializationException("Encountered NULL while deserializing input."); } // Primitives. input = Structure.FromPrimitive(input); if (input is Structure) { return((Structure)input); } IJsonDict dict = input as IJsonDict; if (dict == null) { throw new SerializationException("Deserializing from a " + input.GetType().Name + " is unsupported."); } // Get the deserializer for this object. // This will fail and throw an exception(by design) on unsupported types. // "ref" is also considered an unsupported type. If we see it here, it's either the top-level element // (in which case there are no other elements it could possibly be referencing), or we somehow failed // to replace it during the reference replacement run. TypeHandler handler = registry.GetDeserializer(GetTypeIdentifier(dict)).CreateHandler(this); ICollectionHandler ich = handler as ICollectionHandler; object result; if (ich != null) { // If we have a collection handler and haven't scanned for backrefs yet, scan for them. if (deserializerState == null) { ResolveReferences(ich, dict); } // Is this something we've already resolved? If so, return that reference. result = deserializerState.results.GetValueOrDefault(dict); if (result != null) { return(result); } } result = handler.ProxyDeserialize(dict); if (ich != null) { deserializerState.results[dict] = result; } return(result); }
public override IEnumerable <IEnumerable> GetContainers(IJsonDict source) { this.Validate(source); var result = new List <IEnumerable>(3); if (source.ContainsKey("data")) { result.Add((IJsonDict)source["data"]); } if (source.ContainsKey("keys")) { result.Add((IJsonList)source["keys"]); } if (source.ContainsKey("values")) { result.Add((IJsonList)source["values"]); } return(result); }
public override VesselTarget Deserialize(IJsonDict source) { EnsureValueIsType <string>(source); Guid vesselId; try { vesselId = new Guid((string)source["data"]); } catch (Exception ex) { throw new SerializationException("Provided vessel GUID is invalid.", ex); } Vessel vessel = GetVesselById(vesselId); if (vessel == null) { return(null); // kOS won't really like this, but meh. } return(VesselTarget.CreateOrGetExisting(vessel, serializer.SharedObjects)); }
protected List <double> GetElements(IJsonDict source, int numElements = 0) { EnsureValueIsType <IJsonList>(source); IJsonList value = (IJsonList)source["data"]; if (numElements != 0 && value.Count != numElements) { throw new SerializationException( string.Format( "{0} object: Expected data field to contain {1} elements, but it contained {2} instead.", this.info.Name, numElements, value.Count ) ); } try { return(value.Cast <double>().ToList()); } catch (InvalidCastException) { throw new SerializationException(string.Format("{0} object: All elements of data must be numeric values.", info.Name)); } }
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); }
public override Vector Deserialize(IJsonDict source) { var elements = GetElements(source, 3); return(new Vector(elements[0], elements[1], elements[2])); }
public abstract IEnumerable <IEnumerable> GetContainers(IJsonDict source);
/// <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); }
public object ProxyDeserialize(IJsonDict source) { return(DeserializeMethod.Invoke(this, new object[] { source })); }