diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..898962d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,36 @@
+/[Ll]ibrary/
+/[Tt]emp/
+/[Oo]bj/
+/[Bb]uild/
+/[Bb]uilds/
+/Assets/AssetStoreTools*
+
+# Ignore Editor Tests for now
+/Assets/Editor*
+
+# Visual Studio 2015 cache directory
+/.vs/
+
+# Autogenerated VS/MD/Consulo solution and project files
+ExportedObj/
+.consulo/
+*.csproj
+*.unityproj
+*.sln
+*.suo
+*.tmp
+*.user
+*.userprefs
+*.pidb
+*.booproj
+*.svd
+*.pdb
+
+# Unity3D generated meta files
+*.pidb.meta
+
+# Unity3D Generated File On Crash Reports
+sysinfo.txt
+
+# Builds
+*.apk
\ No newline at end of file
diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta
new file mode 100644
index 0000000..7561fb6
--- /dev/null
+++ b/Assets/Plugins.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 6131a24f85f494c2babb4da56bf30ee1
+folderAsset: yes
+timeCreated: 1501101584
+licenseType: Free
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON.meta b/Assets/Plugins/UnityJSON.meta
new file mode 100644
index 0000000..af85c0a
--- /dev/null
+++ b/Assets/Plugins/UnityJSON.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: a18ed8a5ad0da4df5add1e7429d0e5cf
+folderAsset: yes
+timeCreated: 1501101649
+licenseType: Free
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/Attributes.cs b/Assets/Plugins/UnityJSON/Attributes.cs
new file mode 100644
index 0000000..8add72b
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Attributes.cs
@@ -0,0 +1,323 @@
+using SimpleJSON;
+using System;
+using System.Collections.Generic;
+
+namespace UnityJSON
+{
+ ///
+ /// Defines the JSON serialization and deserialization options for a
+ /// field or a property. If the field or the property does not have this
+ /// attribute, the default options are used. For private fields and
+ /// properties, this attribute is mandatory.
+ ///
+ [AttributeUsage (AttributeTargets.Field | AttributeTargets.Property)]
+ public class JSONNodeAttribute : Attribute
+ {
+ private NodeOptions _options;
+ private string _key = null;
+
+ public JSONNodeAttribute (NodeOptions options) : base ()
+ {
+ _options = options;
+ }
+
+ public JSONNodeAttribute () : base ()
+ {
+ _options = NodeOptions.Default;
+ }
+
+ ///
+ /// The custom key value for this field/property when serializing
+ /// or deserializing. If this value is null, the field/property
+ /// name is used instead.
+ ///
+ public string key {
+ get { return _key; }
+ set { _key = value == "" ? null : value; }
+ }
+
+ ///
+ /// The serialization/deserialization options associated with this
+ /// field/property.
+ ///
+ /// The options.
+ public NodeOptions options {
+ get { return _options; }
+ }
+ }
+
+ ///
+ /// Defines serialization/deserialization customization for enums.
+ /// If no attribute is assigned to the enum, the names of the members
+ /// are simply used as strings.
+ ///
+ [AttributeUsage (AttributeTargets.Enum)]
+ public class JSONEnumAttribute : Attribute
+ {
+ private bool _useIntegers = false;
+ private JSONEnumMemberFormating _format = JSONEnumMemberFormating.None;
+ private string _prefix;
+ private string _suffix;
+
+ ///
+ /// When true the numeric values of the enum members are used
+ /// for serialization/deserialization. Defaults to false.
+ ///
+ public bool useIntegers {
+ get { return _useIntegers; }
+ set { _useIntegers = value; }
+ }
+
+ ///
+ /// Applies a formatting to the member names of the enumeration before
+ /// serializing/deserializing.
+ ///
+ public JSONEnumMemberFormating format {
+ get { return _format; }
+ set { _format = value; }
+ }
+
+ ///
+ /// Applies a prefix to the member names of the enumeration before
+ /// serializing/deserializing. The prefix is added after the
+ /// formatting is applied.
+ ///
+ public string prefix {
+ get { return _prefix; }
+ set { _prefix = value == "" ? null : value; }
+ }
+
+ ///
+ /// Applies a suffix to the member names of the enumeration before
+ /// serializing/deserializing. The suffix is added after the
+ /// formatting is applied.
+ ///
+ public string suffix {
+ get { return _suffix; }
+ set { _suffix = value == "" ? null : value; }
+ }
+ }
+
+ ///
+ /// Defines general serialization/deserialization options applied to the
+ /// custom class or struct. These options are not node-specific and are
+ /// applied every time that class/struct is used. If the class or the
+ /// struct does not have this attribute, the default options are used.
+ ///
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct)]
+ public class JSONObjectAttribute : Attribute
+ {
+ private ObjectOptions _options;
+
+ public JSONObjectAttribute (ObjectOptions options) : base ()
+ {
+ _options = options;
+ }
+
+ public JSONObjectAttribute () : base ()
+ {
+ _options = ObjectOptions.Default;
+ }
+
+ ///
+ /// The general serialization/deserialization options associated
+ /// with this class/struct.
+ ///
+ public ObjectOptions options {
+ get { return _options; }
+ }
+ }
+
+ ///
+ /// Defines the field/property where the unknown keys for a class or
+ /// a struct can be deserialized. Can only be used together with a
+ /// field or property of type Dictionary. If there
+ /// are multiple fields/properties with this attribute, only the first
+ /// one is used.
+ ///
+ [AttributeUsage (AttributeTargets.Field | AttributeTargets.Property)]
+ public class JSONExtrasAttribute : Attribute
+ {
+ private NodeOptions _options;
+
+ public JSONExtrasAttribute (NodeOptions options) : base ()
+ {
+ _options = options;
+ }
+
+ public JSONExtrasAttribute () : base ()
+ {
+ _options = NodeOptions.Default;
+ }
+
+ ///
+ /// The serialization/deserialization options associated with
+ /// this field/property.
+ ///
+ public NodeOptions options {
+ get { return _options; }
+ }
+ }
+
+ ///
+ /// Restricts the deserialization types for a field/property of type
+ /// object. This can also be used to add custom types to the deserialization
+ /// process as per default only primitive types, and arrays and dictionaries
+ /// thereof are created.
+ ///
+ /// This attribute can be used with fields and properties of type object,
+ /// list/array of objects or a dictionary with value type object. For dictionaries,
+ /// the restriction is only applied to the value type.
+ ///
+ [AttributeUsage (AttributeTargets.Field | AttributeTargets.Property)]
+ public class RestrictTypeAttribute : Attribute
+ {
+ private ObjectTypes _types;
+ private Type[] _customTypes;
+
+ public RestrictTypeAttribute (ObjectTypes types) : base ()
+ {
+ _types = types;
+ }
+
+ public RestrictTypeAttribute (ObjectTypes types, Type[] customTypes) : base ()
+ {
+ if (customTypes == null) {
+ throw new ArgumentNullException ("customTypes");
+ }
+ }
+
+ ///
+ /// The types that are allowed for this field/property.
+ ///
+ public ObjectTypes types {
+ get { return _types; }
+ }
+
+ ///
+ /// Custom types that can be deserialized for this object. ObjectTypes
+ /// must allow custom types or an exception is thrown. The order of the
+ /// types are important as they will be tried one by one by the
+ /// deserializer.
+ ///
+ public Type[] customTypes {
+ get { return _customTypes; }
+ set {
+ if (!_types.SupportsCustom ()) {
+ throw new ArgumentException ("Attribute does not support custom types.");
+ }
+
+ List typeList = new List ();
+ HashSet typeSet = new HashSet ();
+ foreach (Type type in value) {
+ if (type != null
+ && !typeSet.Contains (type)
+ && Util.IsCustomType (type)) {
+ typeSet.Add (type);
+ typeList.Add (type);
+ }
+ }
+
+ if (typeList.Count != 0) {
+ _customTypes = typeList.ToArray ();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Adapts the instantiated class. If the node has the given
+ /// key / value pair, then the referenced type is instantiated.
+ /// This can be used together with interfaces or abstract classes
+ /// to determine the final class to be instantiated. One class or
+ /// interface can have multiple conditional attributes. The conditions
+ /// are proved in the order they are given and the type of the first
+ /// fulfilled condition is used.
+ ///
+ [AttributeUsage (
+ AttributeTargets.Class |
+ AttributeTargets.Interface,
+ AllowMultiple = true)]
+ public class ConditionalInstantiationAttribute : Attribute
+ {
+ private Type _reference;
+ private string _key;
+ private object _value;
+
+ public ConditionalInstantiationAttribute (
+ Type reference,
+ string key,
+ object value) : base ()
+ {
+ if (reference == null) {
+ throw new ArgumentNullException ("reference");
+ }
+ if (key == null) {
+ throw new ArgumentNullException ("key");
+ }
+ if (value == null) {
+ throw new ArgumentNullException ("value");
+ }
+ _reference = reference;
+ _key = key;
+ _value = value;
+ }
+
+ ///
+ /// The reference type to be instantiated.
+ ///
+ public Type referenceType {
+ get { return _reference; }
+ }
+
+ ///
+ /// The key for the key / value condition pair.
+ ///
+ public string key {
+ get { return _key; }
+ }
+
+ ///
+ /// The value for the key / value condition pair.
+ ///
+ public object value {
+ get { return _value; }
+ }
+
+ ///
+ /// Removes the key / value pair if the condition is
+ /// matched. This can be useful if the pair does not
+ /// contain any data for the class / struct in order to
+ /// prevent any unknown key errors.
+ ///
+ public bool removeKey { get; set; }
+ }
+
+ ///
+ /// Adapts the default type to be instantiated for this class
+ /// or interface. This is checked after all of the conditional
+ /// attributes (see ConditionalInstantiationAttribute) fail.
+ ///
+ [AttributeUsage (
+ AttributeTargets.Class |
+ AttributeTargets.Interface)]
+ public class DefaultInstantiationAttribute : Attribute
+ {
+ private Type _reference;
+
+ public DefaultInstantiationAttribute (Type reference) : base ()
+ {
+ if (reference == null) {
+ throw new ArgumentNullException ("reference");
+ }
+ _reference = reference;
+ }
+
+ ///
+ /// The reference type to be instantiated.
+ ///
+ public Type referenceType {
+ get { return _reference; }
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/Attributes.cs.meta b/Assets/Plugins/UnityJSON/Attributes.cs.meta
new file mode 100644
index 0000000..4db4e68
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Attributes.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 870c19a136b8843269b388ffb07a95c5
+timeCreated: 1501102207
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/Deserializer.cs b/Assets/Plugins/UnityJSON/Deserializer.cs
new file mode 100644
index 0000000..31888af
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Deserializer.cs
@@ -0,0 +1,1063 @@
+using SimpleJSON;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+namespace UnityJSON
+{
+ ///
+ /// An exception during the deserialization process.
+ ///
+ public class DeserializationException : Exception
+ {
+ public DeserializationException () : base ()
+ {
+ }
+
+ public DeserializationException (string message) : base (message)
+ {
+ }
+ }
+
+ ///
+ /// Deserializes JSON string either into newly instantiated or
+ /// previously existing objects.
+ ///
+ public class Deserializer
+ {
+ private static Deserializer _default = new Deserializer ();
+ private static Deserializer _simple = _default;
+
+ ///
+ /// The default deserializer to be used when no deserializer is given.
+ /// You can set this to your own default deserializer. Uses the
+ /// #Simple deserializer by default.
+ ///
+ public static Deserializer Default {
+ get { return _default; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException ("default deserializer");
+ }
+ _simple = value;
+ }
+ }
+
+ ///
+ /// The initial deserializer that is provided by the framework.
+ ///
+ public static Deserializer Simple {
+ get { return _simple; }
+ }
+
+ ///
+ /// Tries to instantiate an object of a given type. This will be called
+ /// for all custom objects before trying to instantiate the object with a
+ /// default constructor.
+ ///
+ /// Subclasses should override this method to provide instantiated versions
+ /// for classes with constructors with arguments or interfaces or abstract
+ /// classes. The JSON node can be used to decide which class or struct to
+ /// instantiate.
+ ///
+ protected virtual bool TryInstantiate (
+ JSONNode node,
+ Type type,
+ NodeOptions options,
+ out object instantiatedObject)
+ {
+ instantiatedObject = null;
+ return false;
+ }
+
+ ///
+ /// Tries to deserialize the JSON node onto the given object. It is guaranteed
+ /// that the object is not null. This will be called before trying any other
+ /// deserialization method. Subclasses should override this method to perform
+ /// their own deserialization logic.
+ ///
+ protected virtual bool TryDeserializeOn (
+ object obj,
+ JSONNode node,
+ NodeOptions options)
+ {
+ return false;
+ }
+
+ ///
+ /// Deserializes the JSON string directly on the object. Throws an
+ /// ArgumentNullException of the object is null .
+ ///
+ public void DeserializeOn (
+ object obj,
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (obj == null) {
+ throw new ArgumentNullException ("obj");
+ }
+
+ if (TryDeserializeOn (obj, node, options)) {
+ return;
+ }
+
+ Type type = obj.GetType ();
+ if (type.IsEnum) {
+ throw new ArgumentException ("Cannot deserialize on enums.");
+ } else if (type.IsPrimitive) {
+ throw new ArgumentException ("Cannot deserialize on primitive types.");
+ } else if (!node.IsObject) {
+ throw new ArgumentException ("Expected a JSON object, found " + node.Tag);
+ }
+
+ _FeedCustom (obj, node, options);
+ }
+
+ ///
+ /// Deserializes the JSON node to a new object of the requested type. This
+ /// will first call #TryInstantiate to create an object for the type, then
+ /// try the default constructor without arguments. If an object can be
+ /// instantiated, then first the IDeserializable.Deserialize method will
+ /// be used if the object implements the interface. If not, the framework
+ /// deserialization will be performed.
+ ///
+ /// JSON node to deserialize.
+ /// Requested type of the deserialized object.
+ /// Deserialization options for the node (optional).
+ public object Deserialize (
+ JSONNode node,
+ Type type,
+ NodeOptions options = NodeOptions.Default)
+ {
+ return _Deserialize (node, type, options, ObjectTypes.JSON, null);
+ }
+
+ ///
+ /// Deserializes a JSON node into a C# System.Object type. If no restrictions
+ /// are given, the deserialized types can be doubles, booleans, strings, and arrays
+ /// and dictionaries thereof. Restricted types can allow custom types to create
+ /// classes or structs instead of dictionaries.
+ ///
+ /// JSON node to deserialize.
+ /// Restricted types for the object.
+ /// Allowed custom types for the object. Restrictions
+ /// must allow custom types if not null .
+ /// Deserialization options.
+ public object DeserializeToObject (
+ JSONNode node,
+ ObjectTypes restrictedTypes = ObjectTypes.JSON,
+ Type[] customTypes = null,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ if (customTypes != null) {
+ if (!restrictedTypes.SupportsCustom ()) {
+ throw new ArgumentException ("Restrictions do not allow custom types.");
+ }
+ foreach (Type type in customTypes) {
+ if (!Util.IsCustomType (type)) {
+ throw new ArgumentException ("Unsupported custom type: " + type);
+ }
+ }
+ }
+ return _DeserializeToObject (node, options, restrictedTypes, customTypes);
+ }
+
+ ///
+ /// Deserializes a JSON node into a System.Nullable object.
+ ///
+ public Nullable DeserializeToNullable (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default) where T : struct
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ return (Nullable) Deserialize (node, typeof(T), options);
+ }
+
+ ///
+ /// Deserializes a JSON node into an integer. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain an integer.
+ ///
+ public int DeserializeToInt (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (int)_DeserializeToInt (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into an unsigned integer. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain an unsigned integer.
+ ///
+ public uint DeserializeToUInt (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (uint)_DeserializeToUInt (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a byte. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain a byte.
+ ///
+ public byte DeserializeToByte (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (byte)_DeserializeToByte (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a boolean. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain a boolean.
+ ///
+ public bool DeserializeToBool (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (bool)_DeserializeToBool (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a float. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain a float.
+ ///
+ public float DeserializeToFloat (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (float)_DeserializeToFloat (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a double. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain a double.
+ ///
+ public double DeserializeToDouble (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (double)_DeserializeToDouble (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a long. Throws an ArgumentNullException
+ /// if the node is null . Throws a CastException if the node does
+ /// not contain a long.
+ ///
+ public long DeserializeToLong (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null) {
+ throw new ArgumentNullException ("node");
+ }
+ return (long)_DeserializeToLong (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a string.
+ ///
+ public string DeserializeToString (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ return _DeserializeToString (node, options);
+ }
+
+ ///
+ /// Deserializes a JSON node into an enum. Throws an ArgumentNullException
+ /// if the node is null . Throws an ArgumentException if the generic
+ /// type T is not an enum.
+ ///
+ public T DeserializeToEnum (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ throw new ArgumentNullException ("node");
+ }
+ if (!typeof(T).IsEnum) {
+ throw new ArgumentException ("Generic type is not an enum.");
+ }
+ return (T)_DeserializeToEnum (node, typeof(T), options);
+ }
+
+ ///
+ /// Deserializes a JSON node into a generic list.
+ ///
+ public List DeserializeToList (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ var list = new List ();
+ _FeedList (list, node, typeof(T), options);
+ return list;
+ }
+
+ ///
+ /// Deserializes a JSON node into a System.Object list. If no restrictions
+ /// are given, the deserialized types can be doubles, booleans, strings, and arrays
+ /// and dictionaries thereof. Restricted types can allow custom types to create
+ /// classes or structs instead of dictionaries.
+ ///
+ /// JSON node to deserialize.
+ /// Restricted types for the object.
+ /// Allowed custom types for the object. Restrictions
+ /// must allow custom types if not null .
+ /// Deserialization options.
+ public List DeserializeToObjectList (
+ JSONNode node,
+ ObjectTypes restrictedTypes = ObjectTypes.JSON,
+ Type[] customTypes = null,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ var list = new List ();
+ _FeedList (list, node, typeof(object), options, restrictedTypes, customTypes);
+ return list;
+ }
+
+ ///
+ /// Deserializes a JSON node into a generic dictionary.
+ ///
+ public Dictionary DeserializeToDictionary (
+ JSONNode node,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ var dictionary = new Dictionary ();
+ _FeedDictionary (dictionary, node, typeof(K), typeof(V), options);
+ return dictionary;
+ }
+
+ ///
+ /// Deserializes a JSON node into a dictionary with value type System.Object. If
+ /// no restrictions are given, the deserialized value types can be doubles, booleans,
+ /// strings, and arrays and dictionaries thereof. Restricted types can allow custom
+ /// types to create classes or structs instead of dictionaries.
+ ///
+ /// JSON node to deserialize.
+ /// Restricted types for the values.
+ /// Allowed custom types for the values. Restrictions
+ /// must allow custom types if not null .
+ /// Deserialization options.
+ public Dictionary DeserializeToObjectDictionary (
+ JSONNode node,
+ ObjectTypes restrictedTypes = ObjectTypes.JSON,
+ Type[] customTypes = null,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+ var dictionary = new Dictionary ();
+ _FeedDictionary (
+ dictionary,
+ node,
+ typeof(K),
+ typeof(object),
+ options,
+ restrictedTypes,
+ customTypes);
+ return dictionary;
+ }
+
+ private object _Deserialize (
+ JSONNode node,
+ Type type,
+ NodeOptions options,
+ ObjectTypes types,
+ Type[] customTypes)
+ {
+ if (node == null || node.IsNull) {
+ return null;
+ }
+
+ object obj;
+ if (TryInstantiate (node, type, options, out obj)) {
+ DeserializeOn (obj, node, options);
+ return obj;
+ }
+
+ if (type == typeof(object)) {
+ return _DeserializeToObject (node, options, types, customTypes);
+ }
+
+ if (type.IsValueType) {
+ if (type.IsEnum) {
+ return _DeserializeToEnum (node, type, options);
+ } else if (type.IsPrimitive) {
+ return _DeserializeToPrimitive (node, type, options);
+ }
+ } else {
+ if (type == typeof(string)) {
+ return _DeserializeToString (node, options);
+ } else if (Nullable.GetUnderlyingType (type) != null) {
+ return _DeserializeToNullable (node, type, options);
+ } else if (typeof(IList).IsAssignableFrom (type)) {
+ return _DeserializeToIList (node, type, options, types, customTypes);
+ } else if (Util.IsDictionary (type)) {
+ return _DeserializeToIDictionary (node, type, options, types, customTypes);
+ }
+ }
+ return _DeserializeCustom (node, type, options);
+ }
+
+ private object _Deserialize (
+ JSONNode node,
+ Type type,
+ NodeOptions options,
+ MemberInfo memberInfo)
+ {
+ var typeAttribute = memberInfo == null
+ ? null : Util.GetAttribute (memberInfo);
+ ObjectTypes types = typeAttribute == null ? ObjectTypes.JSON : typeAttribute.types;
+ Type[] customTypes = typeAttribute == null ? null : typeAttribute.customTypes;
+ return _Deserialize (node, type, options, types, customTypes);
+ }
+
+ private object _DeserializeToObject (
+ JSONNode node,
+ NodeOptions options,
+ ObjectTypes restrictedTypes,
+ Type[] customTypes)
+ {
+ if (node.IsArray) {
+ if (!restrictedTypes.SupportsArray ()) {
+ return _HandleMismatch (options, "Arrays are not supported for object.");
+ }
+ return _DeserializeToArray (
+ node,
+ typeof(object),
+ options,
+ restrictedTypes,
+ customTypes);
+ } else if (node.IsBoolean) {
+ if (!restrictedTypes.SupportsBool ()) {
+ return _HandleMismatch (options, "Bools are not supported for object.");
+ }
+ return node.AsBool;
+ } else if (node.IsNumber) {
+ if (!restrictedTypes.SupportsNumber ()) {
+ return _HandleMismatch (options, "Numbers are not supported for object.");
+ }
+ return node.AsDouble;
+ } else if (node.IsObject) {
+ if (restrictedTypes.SupportsCustom () && customTypes != null) {
+ foreach (Type customType in customTypes) {
+ try {
+ var obj = Deserialize (node, customType, NodeOptions.Default);
+ if (obj != null) {
+ return obj;
+ }
+ } catch (Exception) {
+ }
+ }
+ }
+
+ if (!restrictedTypes.SupportsDictionary ()) {
+ return _HandleMismatch (options, "Dictionaries are not supported for object.");
+ }
+ return _DeserializeToGenericDictionary (
+ node,
+ typeof(string),
+ typeof(object),
+ options,
+ restrictedTypes,
+ customTypes);
+ } else if (node.IsString) {
+ if (!restrictedTypes.SupportsString ()) {
+ return _HandleMismatch (options, "Strings are not supported for object.");
+ }
+ return _DeserializeToString (node, options);
+ } else {
+ return _HandleUnknown (options, "Unknown JSON node type " + node);
+ }
+ }
+
+ private object _DeserializeToNullable (JSONNode node, Type nullableType, NodeOptions options)
+ {
+ Type underlyingType = Nullable.GetUnderlyingType (nullableType);
+ return Deserialize (node, underlyingType, options);
+ }
+
+ private object _DeserializeToPrimitive (JSONNode node, Type type, NodeOptions options)
+ {
+ if (type == typeof(int)) {
+ return _DeserializeToInt (node, options);
+ } else if (type == typeof(byte)) {
+ return _DeserializeToByte (node, options);
+ } else if (type == typeof(long)) {
+ return _DeserializeToByte (node, options);
+ } else if (type == typeof(uint)) {
+ return _DeserializeToUInt (node, options);
+ } else if (type == typeof(bool)) {
+ return _DeserializeToBool (node, options);
+ } else if (type == typeof(float)) {
+ return _DeserializeToFloat (node, options);
+ } else if (type == typeof(double)) {
+ return _DeserializeToDouble (node, options);
+ } else {
+ return _HandleUnknown (options, "Unknown primitive type " + type);
+ }
+ }
+
+ private string _DeserializeToString (JSONNode node, NodeOptions options)
+ {
+ if (!node.IsString) {
+ return _HandleMismatch (options, "Expected string, found: " + node) as string;
+ } else {
+ return node.Value;
+ }
+ }
+
+ private object _DeserializeToInt (JSONNode node, NodeOptions options)
+ {
+ if (node.IsNumber) {
+ int value;
+ if (int.TryParse (node.Value, out value)) {
+ return value;
+ }
+ }
+ return _HandleMismatch (options, "Expected integer, found " + node);
+ }
+
+ private object _DeserializeToUInt (JSONNode node, NodeOptions options)
+ {
+ if (node.IsNumber) {
+ uint value;
+ if (uint.TryParse (node.Value, out value)) {
+ return value;
+ }
+ }
+ return _HandleMismatch (options, "Expected unsigned integer, found " + node);
+ }
+
+ private object _DeserializeToByte (JSONNode node, NodeOptions options)
+ {
+ if (node.IsNumber) {
+ byte value;
+ if (byte.TryParse (node.Value, out value)) {
+ return value;
+ }
+ }
+ return _HandleMismatch (options, "Expected byte, found " + node);
+ }
+
+ private object _DeserializeToLong (JSONNode node, NodeOptions options)
+ {
+ if (node.IsNumber) {
+ long value;
+ if (long.TryParse (node.Value, out value)) {
+ return value;
+ }
+ }
+ return _HandleMismatch (options, "Expected long, found " + node);
+ }
+
+ private object _DeserializeToFloat (JSONNode node, NodeOptions options)
+ {
+ if (node.IsNumber) {
+ return node.AsFloat;
+ }
+ return _HandleMismatch (options, "Expected float, found " + node);
+ }
+
+ private object _DeserializeToDouble (JSONNode node, NodeOptions options)
+ {
+ if (node.IsNumber) {
+ return node.AsDouble;
+ }
+ return _HandleMismatch (options, "Expected double, found " + node);
+ }
+
+ private object _DeserializeToBool (JSONNode node, NodeOptions options)
+ {
+ if (node.IsBoolean) {
+ return node.AsBool;
+ }
+ return _HandleMismatch (options, "Expected integer, found " + node);
+ }
+
+ private object _DeserializeToEnum (JSONNode node, Type enumType, NodeOptions options)
+ {
+ Func handleError = () => _HandleMismatch (
+ options, "Expected enum of type " + enumType + ", found: " + node);
+
+ var enumAttribute = Util.GetAttribute (enumType);
+ if (enumAttribute != null && enumAttribute.useIntegers && node.IsNumber) {
+ try {
+ return Enum.ToObject (enumType, _DeserializeToInt (node, options));
+ } catch (Exception) {
+ }
+ } else if (node.IsString) {
+ string value = node.Value;
+ if (enumAttribute != null) {
+ if (enumAttribute.prefix != null) {
+ if (!value.StartsWith (enumAttribute.prefix)) {
+ return handleError ();
+ } else {
+ value = value.Substring (enumAttribute.prefix.Length);
+ }
+ }
+ if (enumAttribute.suffix != null) {
+ if (!value.EndsWith (enumAttribute.suffix)) {
+ return handleError ();
+ } else {
+ value = value.Substring (0, value.Length - enumAttribute.suffix.Length);
+ }
+ }
+ }
+ try {
+ return Enum.Parse (enumType, value, true);
+ } catch (Exception) {
+ }
+ }
+ return handleError ();
+ }
+
+ private IDictionary _DeserializeToIDictionary (
+ JSONNode node,
+ Type dictionaryType,
+ NodeOptions options,
+ ObjectTypes types,
+ Type[] customTypes)
+ {
+ Type genericType = dictionaryType.IsGenericType ? (dictionaryType.IsGenericTypeDefinition
+ ? dictionaryType : dictionaryType.GetGenericTypeDefinition ()) : null;
+ if (dictionaryType == typeof(IDictionary)) {
+ return _DeserializeToGenericDictionary (
+ node,
+ typeof(string),
+ typeof(object),
+ options,
+ types,
+ customTypes);
+ } else if (genericType == typeof(IDictionary<,>) || genericType == typeof(Dictionary<,>)) {
+ var args = dictionaryType.GetGenericArguments ();
+ return _DeserializeToGenericDictionary (
+ node,
+ args [0],
+ args [1],
+ options,
+ types,
+ customTypes);
+ } else {
+ return _HandleUnknown (options, "Unknown dictionary type " + dictionaryType) as IDictionary;
+ }
+ }
+
+ private IList _DeserializeToIList (
+ JSONNode node,
+ Type listType,
+ NodeOptions options,
+ ObjectTypes types,
+ Type[] customTypes)
+ {
+ Type genericType = listType.IsGenericType ? (listType.IsGenericTypeDefinition
+ ? listType : listType.GetGenericTypeDefinition ()) : null;
+ if (listType == typeof(Array)) {
+ return _DeserializeToArray (
+ node,
+ typeof(object),
+ options,
+ types,
+ customTypes);
+ } else if (listType.IsArray) {
+ return _DeserializeToArray (
+ node,
+ listType.GetElementType (),
+ options,
+ types,
+ customTypes);
+ } else if (listType == typeof(IList)) {
+ return _DeserializeToGenericList (
+ node,
+ typeof(object),
+ options,
+ types,
+ customTypes);
+ } else if (genericType == typeof(IList<>) || genericType == typeof(List<>)) {
+ return _DeserializeToGenericList (
+ node,
+ listType.GetGenericArguments () [0],
+ options,
+ types,
+ customTypes);
+ } else {
+ return _HandleUnknown (options, "Unknown list type " + listType) as IList;
+ }
+ }
+
+ private Array _DeserializeToArray (
+ JSONNode node,
+ Type elementType,
+ NodeOptions options,
+ ObjectTypes types,
+ Type[] customTypes)
+ {
+ IList list = _DeserializeToGenericList (
+ node,
+ elementType,
+ options,
+ types,
+ customTypes);
+ Array array = Array.CreateInstance (elementType, list.Count);
+ list.CopyTo (array, 0);
+ return array;
+ }
+
+ private IList _DeserializeToGenericList (
+ JSONNode node,
+ Type genericArgument,
+ NodeOptions options,
+ ObjectTypes types = ObjectTypes.JSON,
+ Type[] customTypes = null)
+ {
+ IList list = (IList)Activator.CreateInstance (typeof(List<>).MakeGenericType (genericArgument));
+ _FeedList (list, node, genericArgument, options, types, customTypes);
+ return list;
+ }
+
+ private void _FeedList (
+ IList list,
+ JSONNode node,
+ Type genericArgument,
+ NodeOptions options,
+ ObjectTypes types = ObjectTypes.JSON,
+ Type[] customTypes = null)
+ {
+ if (node.IsArray) {
+ JSONArray array = node as JSONArray;
+ IEnumerator enumerator = array.GetEnumerator ();
+ while (enumerator.MoveNext ()) {
+ JSONNode child = (JSONNode)enumerator.Current;
+ // Throws an error if needed.
+ list.Add (_Deserialize (
+ child,
+ genericArgument,
+ options & ~NodeOptions.ReplaceDeserialized,
+ types,
+ customTypes));
+ }
+ } else {
+ _HandleMismatch (options, "Expected an array, found " + node);
+ }
+ }
+
+ private IDictionary _DeserializeToGenericDictionary (
+ JSONNode node,
+ Type keyType,
+ Type valueType,
+ NodeOptions options,
+ ObjectTypes types = ObjectTypes.JSON,
+ Type[] customTypes = null)
+ {
+ IDictionary dictionary = (IDictionary)Activator
+ .CreateInstance (typeof(Dictionary<,>)
+ .MakeGenericType (keyType, valueType));
+ _FeedDictionary (dictionary, node, keyType, valueType, options, types, customTypes);
+ return dictionary;
+ }
+
+ private void _FeedDictionary (
+ IDictionary dictionary,
+ JSONNode node,
+ Type keyType,
+ Type valueType,
+ NodeOptions options,
+ ObjectTypes types = ObjectTypes.JSON,
+ Type[] customTypes = null)
+ {
+ if (node.IsObject) {
+ JSONObject obj = node as JSONObject;
+ IEnumerator enumerator = obj.GetEnumerator ();
+ while (enumerator.MoveNext ()) {
+ var pair = (KeyValuePair)enumerator.Current;
+ // Use default field options to throw at any error.
+ object key = _Deserialize (
+ new JSONString (pair.Key),
+ keyType,
+ NodeOptions.Default,
+ ObjectTypes.JSON,
+ null /* customTypes */);
+
+ // Throws an error if needed.
+ object value = _Deserialize (
+ pair.Value,
+ valueType,
+ options & ~NodeOptions.ReplaceDeserialized,
+ types,
+ customTypes);
+ dictionary.Add (key, value);
+ }
+ } else {
+ _HandleMismatch (options, "Expected a dictionary, found " + node);
+ }
+ }
+
+ private object _DeserializeCustom (JSONNode node, Type type, NodeOptions options)
+ {
+ var conditionalAttributes = type.GetCustomAttributes (typeof(ConditionalInstantiationAttribute), false);
+ foreach (object attribute in conditionalAttributes) {
+ var condition = attribute as ConditionalInstantiationAttribute;
+ if (Equals (node [condition.key].Value, condition.value.ToString())) {
+ if (condition.removeKey) {
+ node.Remove (condition.key);
+ }
+ return Deserialize (node, condition.referenceType, options);
+ }
+ }
+
+ var defaultAttribute = Util.GetAttribute (type);
+ if (defaultAttribute != null) {
+ return Deserialize (node, defaultAttribute.referenceType, options);
+ }
+
+ object obj;
+ try {
+ obj = Activator.CreateInstance (type);
+ } catch (Exception) {
+ return _HandleUnknown (options, "Unknown type " + type + " cannot be instantiated.");
+ }
+
+ DeserializeOn (obj, node, options);
+ return obj;
+ }
+
+ private void _FeedCustom (object filledObject, JSONNode node, NodeOptions options)
+ {
+ if (filledObject is IDeserializable) {
+ (filledObject as IDeserializable).Deserialize (node, this);
+ return;
+ }
+
+ var listener = filledObject as IDeserializationListener;
+ if (listener != null) {
+ listener.OnDeserializationWillBegin (this);
+ }
+
+ if (node.IsObject) {
+ try {
+ Type type = filledObject.GetType ();
+
+ MemberInfo extrasMember = null;
+ JSONExtrasAttribute extrasAttribute = null;
+ Dictionary extras = new Dictionary ();
+
+ var members = _GetDeserializedClassMembers (type, out extrasMember, out extrasAttribute);
+ JSONObject obj = node as JSONObject;
+ IEnumerator enumerator = obj.GetEnumerator ();
+
+ var extrasTypeAttribute = extrasMember == null
+ ? null : Util.GetAttribute (extrasMember);
+ ObjectTypes extrasTypes = extrasTypeAttribute == null
+ ? ObjectTypes.JSON : extrasTypeAttribute.types;
+ Type[] extrasCustomTypes = extrasTypeAttribute == null
+ ? null : extrasTypeAttribute.customTypes;
+
+ while (enumerator.MoveNext ()) {
+ var pair = (KeyValuePair)enumerator.Current;
+ if (members.ContainsKey (pair.Key)) {
+ _DeserializeClassMember (filledObject, members [pair.Key], pair.Value);
+ } else {
+ if (extrasMember != null) {
+ extras.Add (pair.Key, _DeserializeToObject (
+ pair.Value,
+ extrasAttribute.options,
+ extrasTypes,
+ extrasCustomTypes));
+ continue;
+ }
+
+ var objectAttribute = Util.GetAttribute (type);
+ if (objectAttribute == null || objectAttribute.options.ShouldThrowAtUnknownKey ()) {
+ throw new DeserializationException ("The key " + pair.Key + " does not exist "
+ + "in class " + type);
+ }
+ }
+ }
+
+ if (extrasMember != null) {
+ if (extras.Count != 0 || extrasAttribute.options.ShouldAssignNull ()) {
+ Util.SetMemberValue (extrasMember, filledObject, extras);
+ }
+ }
+
+ if (listener != null) {
+ listener.OnDeserializationSucceeded (this);
+ }
+ } catch (Exception exception) {
+ if (listener != null) {
+ listener.OnDeserializationFailed (this);
+ }
+ throw exception;
+ }
+ } else {
+ if (listener != null) {
+ listener.OnDeserializationFailed (this);
+ }
+ _HandleMismatch (options, "Expected a JSON object, found " + node);
+ }
+ }
+
+ private void _DeserializeClassMember (
+ object filledObject,
+ List memberInfos,
+ JSONNode node)
+ {
+ for (int i = 0; i < memberInfos.Count; i++) {
+ var memberInfo = memberInfos [i];
+ var fieldAttribute = Util.GetAttribute (memberInfo);
+ var options = fieldAttribute != null ? fieldAttribute.options : NodeOptions.Default;
+
+ try {
+ Type type = Util.GetMemberType (memberInfo);
+ if (node.IsObject
+ && !type.IsValueType
+ && !typeof(IDictionary).IsAssignableFrom (type)
+ && !options.ShouldReplaceWithDeserialized ()) {
+ var value = Util.GetMemberValue (memberInfo, filledObject);
+ if (value != null) {
+ DeserializeOn (value, node, options);
+ return;
+ }
+ }
+
+ object deserialized = _Deserialize (node, type, options, memberInfo);
+ if (deserialized != null || options.ShouldAssignNull ()) {
+ Util.SetMemberValue (memberInfo, filledObject, deserialized);
+ return;
+ }
+ } catch (Exception ex) {
+ if (i == memberInfos.Count - 1) {
+ throw ex;
+ }
+ }
+ }
+ }
+
+ private Dictionary> _GetDeserializedClassMembers (
+ Type classType,
+ out MemberInfo extrasMember,
+ out JSONExtrasAttribute extrasAttribute)
+ {
+ JSONObjectAttribute classAttribute = Util.GetAttribute (classType);
+ Dictionary> members = new Dictionary> ();
+
+ var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+ if (classAttribute != null && !classAttribute.options.ShouldIgnoreStatic ()) {
+ flags |= BindingFlags.Static;
+ }
+
+ extrasMember = null;
+ extrasAttribute = null;
+
+ foreach (var fieldInfo in classType.GetFields(flags)) {
+ if (extrasMember == null) {
+ if (Util.IsJSONExtrasMember (fieldInfo, out extrasAttribute)) {
+ extrasMember = fieldInfo;
+ continue;
+ }
+ }
+
+ var fieldAttribute = Util.GetAttribute (fieldInfo);
+ if (fieldAttribute != null && !fieldAttribute.options.IsDeserialized ()) {
+ continue;
+ } else if (!fieldInfo.IsLiteral && (fieldInfo.IsPublic || fieldAttribute != null)) {
+ string key = (fieldAttribute != null && fieldAttribute.key != null)
+ ? fieldAttribute.key : fieldInfo.Name;
+ if (!members.ContainsKey (key)) {
+ members [key] = new List ();
+ }
+ members [key].Add (fieldInfo);
+ }
+ }
+
+ if (classAttribute == null || !classAttribute.options.ShouldIgnoreProperties ()) {
+ foreach (var propertyInfo in classType.GetProperties(flags)) {
+ if (extrasMember == null) {
+ if (Util.IsJSONExtrasMember (propertyInfo, out extrasAttribute)) {
+ extrasMember = propertyInfo;
+ continue;
+ }
+ }
+
+ var fieldAttribute = Util.GetAttribute (propertyInfo);
+ if (fieldAttribute != null && !fieldAttribute.options.IsDeserialized ()) {
+ continue;
+ } else if (propertyInfo.GetIndexParameters ().Length == 0 && propertyInfo.CanWrite &&
+ (fieldAttribute != null || propertyInfo.GetSetMethod (false) != null)) {
+ string key = (fieldAttribute != null && fieldAttribute.key != null)
+ ? fieldAttribute.key : propertyInfo.Name;
+ if (!members.ContainsKey (key)) {
+ members [key] = new List ();
+ }
+ members [key].Add (propertyInfo);
+ }
+ }
+ }
+
+ return members;
+ }
+
+ private object _HandleMismatch (NodeOptions options, string message)
+ {
+ if (!options.ShouldIgnoreTypeMismatch ()) {
+ throw new DeserializationException (message);
+ } else {
+ return null;
+ }
+ }
+
+ private object _HandleUnknown (NodeOptions options, string message)
+ {
+ if (!options.ShouldIgnoreUnknownType ()) {
+ throw new DeserializationException (message);
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/Deserializer.cs.meta b/Assets/Plugins/UnityJSON/Deserializer.cs.meta
new file mode 100644
index 0000000..be5d1a7
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Deserializer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b8fef390dd220476eb25f623b29ad0f0
+timeCreated: 1505244350
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/Enums.cs b/Assets/Plugins/UnityJSON/Enums.cs
new file mode 100644
index 0000000..650bfef
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Enums.cs
@@ -0,0 +1,335 @@
+namespace UnityJSON
+{
+ ///
+ /// Serialization/deserialization options for a single
+ /// JSON node. These can be defined for the fields and properties
+ /// of a class with the use of the JSONNodeAttribute. If no
+ /// attribute is given, the default options are used.
+ ///
+ public enum NodeOptions
+ {
+ ///
+ /// Default options for the serialization and deserialization
+ /// of this node which disables all the other node options.
+ ///
+ Default = 0,
+
+ ///
+ /// If true the field or the property is not serialized.
+ /// This can be used with public fields / properties to
+ /// ignore them during serialization.
+ ///
+ DontSerialize = 1,
+
+ ///
+ /// If true the field or the property is not deserialized.
+ /// This can be used with public fields / properties to
+ /// ignore them during deserialization.
+ ///
+ DontDeserialize = 1 << 1,
+
+ ///
+ /// Per default, if a field or a property has the value null
+ /// then it is ignored at serialization. When used, this option
+ /// forces the field to be serialized as either null or undefined
+ /// (see Serializer.useUndefinedForNull).
+ ///
+ SerializeNull = 1 << 2,
+
+ ///
+ /// Per default if the JSON data does not match the C# type, the
+ /// deserializer throws an error. When used, this forces the deserializer
+ /// to ignore this error and simply return null from the deserialization.
+ ///
+ IgnoreTypeMismatch = 1 << 3,
+
+ ///
+ /// If the C# type cannot be instantiated, then an error is thrown.
+ /// This can for instance happen for classes with custom constructors
+ /// that are not defined in the deserializer. When used, this option
+ /// forces the deserializer to ignore this error and simply return null
+ /// from the deserialization.
+ ///
+ IgnoreUnknownType = 1 << 4,
+
+ ///
+ /// Ignore both the type mismatch and the unknown type errors for
+ /// deserialization.
+ ///
+ IgnoreDeserializationTypeErrors = IgnoreTypeMismatch | IgnoreUnknownType,
+
+ ///
+ /// When deserializing a JSON string, the null or undefined values are
+ /// not assigned and simply ignored. When used, this option makes sure
+ /// that the null values are applied to this field or property. If this
+ /// has a primitive type, then the default value (0 for integer, false
+ /// for boolean etc) is assigned.
+ ///
+ DontAssignNull = 1 << 5,
+
+ ///
+ /// By default, the custom classes (all except string, nullables and
+ /// enumerables) are not assigned anew but rather reused. For instance,
+ /// assume we have classes A and B, the class A has field classB of
+ /// type B, class B has a field intField of type int. When deserializing A,
+ /// the deserializer by default sets the value of intField directly instead
+ /// of creating a new instance of class B with the new intField value. When
+ /// ReplaceDeserialized option is used on the field classB, the deserializer
+ /// creates a new instance of class B and assigns it directly instead of
+ /// working with the current value.
+ ///
+ ReplaceDeserialized = 1 << 6
+ }
+
+ ///
+ /// General serialization/deserialization options assigned to
+ /// all instances of a class or a struct. You can specify these options
+ /// by using a JSONObjectAttribute.
+ ///
+ public enum ObjectOptions
+ {
+ ///
+ /// Default options for the serialization and deserialization
+ /// of this class or struct which disables all the other object options.
+ ///
+ Default = 0,
+
+ ///
+ /// Ignores the properties when serializing or deserializing. This
+ /// can also be used to simply increase the performance if no properties
+ /// are used for the serialization / deserialization.
+ ///
+ IgnoreProperties = 1,
+
+ ///
+ /// Per default, the static fields and properties are ignored for
+ /// the serialization and deserialization. When used, all public
+ /// and non-public static fields and properties are considered for
+ /// serialization and deserialization just like the non-static ones.
+ ///
+ IncludeStatic = 1 << 1,
+
+ ///
+ /// When deserializing the JSON, there can be unknown nodes that
+ /// do not match the class or struct definition. If there also isn't
+ /// any field / property with JSONExtrasAttribute to collect the unknown
+ /// keys, then an exception is thrown. This option prevents the
+ /// deserializer from throwing that exception.
+ ///
+ IgnoreUnknownKey = 1 << 2
+ }
+
+ ///
+ /// The types that are supported for deserialization for a general
+ /// System.Object type.
+ ///
+ public enum ObjectTypes
+ {
+ ///
+ /// Default value simply deserializes the JSON objects into
+ /// their C# counterparts as in strings, booleans, doubles
+ /// and arrays and dictionaries thereof.
+ ///
+ JSON = String | Bool | Number | Array | Dictionary,
+
+ ///
+ /// Allows all types including custom types.
+ ///
+ All = JSON | Custom,
+
+ ///
+ /// Allows strings.
+ ///
+ String = 1,
+
+ ///
+ /// Allows booleans.
+ ///
+ Bool = 1 << 1,
+
+ ///
+ /// Allows numbers in form of doubles.
+ ///
+ Number = 1 << 2,
+
+ ///
+ /// Allows arrays of the supported
+ /// object types.
+ ///
+ Array = 1 << 3,
+
+ ///
+ /// Allows dictionaries with string keys
+ /// and values of supported object types.
+ ///
+ Dictionary = 1 << 4,
+
+ ///
+ /// Allows custom types. These must be defined
+ /// in a separate type array.
+ ///
+ Custom = 1 << 5
+ }
+
+ ///
+ /// Formatting to be applied to enum members before
+ /// serializing or deserializing them.
+ ///
+ public enum JSONEnumMemberFormating
+ {
+ ///
+ /// No formatting is applied.
+ ///
+ None,
+
+ ///
+ /// The member name is lowecased.
+ ///
+ Lowercased,
+
+ ///
+ /// The member name is uppercased.
+ ///
+ Uppercased,
+
+ ///
+ /// The member name is capitalized with the
+ /// only first letter capital.
+ ///
+ Capitalized
+ }
+
+ ///
+ /// Provides helper methods to query options.
+ ///
+ public static class OptionsExtensions
+ {
+ ///
+ /// Returns true if NodeOptions.DontSerialize is not set.
+ ///
+ public static bool IsSerialized (this NodeOptions options)
+ {
+ return (options & NodeOptions.DontSerialize) == 0;
+ }
+
+ ///
+ /// Returns true if NodeOptions.DontDeserialize is not set.
+ ///
+ public static bool IsDeserialized (this NodeOptions options)
+ {
+ return (options & NodeOptions.DontDeserialize) == 0;
+ }
+
+ ///
+ /// Returns true if NodeOptions.ShouldSerializeNull is set.
+ ///
+ public static bool ShouldSerializeNull (this NodeOptions options)
+ {
+ return (options & NodeOptions.SerializeNull) != 0;
+ }
+
+ ///
+ /// Returns true if NodeOptions.IgnoreTypeMismatch is set.
+ ///
+ public static bool ShouldIgnoreTypeMismatch (this NodeOptions options)
+ {
+ return (options & NodeOptions.IgnoreTypeMismatch) != 0;
+ }
+
+ ///
+ /// Returns true if NodeOptions.IgnoreUnknownType is set.
+ ///
+ public static bool ShouldIgnoreUnknownType (this NodeOptions options)
+ {
+ return (options & NodeOptions.IgnoreUnknownType) != 0;
+ }
+
+ ///
+ /// Returns true if NodeOptions.DontAssignNull is not set.
+ ///
+ public static bool ShouldAssignNull (this NodeOptions options)
+ {
+ return (options & NodeOptions.DontAssignNull) == 0;
+ }
+
+ ///
+ /// Returns true if NodeOptions.ReplaceDeserialized is set.
+ ///
+ public static bool ShouldReplaceWithDeserialized (this NodeOptions options)
+ {
+ return (options & NodeOptions.ReplaceDeserialized) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectOptions.IgnoreProperties is set.
+ ///
+ public static bool ShouldIgnoreProperties (this ObjectOptions options)
+ {
+ return (options & ObjectOptions.IgnoreProperties) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectOptions.IncludeStatic is not set.
+ ///
+ public static bool ShouldIgnoreStatic (this ObjectOptions options)
+ {
+ return (options & ObjectOptions.IncludeStatic) == 0;
+ }
+
+ ///
+ /// Returns true if ObjectOptions.IgnoreUnknownKey is not set.
+ ///
+ public static bool ShouldThrowAtUnknownKey (this ObjectOptions options)
+ {
+ return (options & ObjectOptions.IgnoreUnknownKey) == 0;
+ }
+
+ ///
+ /// Returns true if ObjectTypes.String is set.
+ ///
+ public static bool SupportsString (this ObjectTypes types)
+ {
+ return (types & ObjectTypes.String) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectTypes.Bool is set.
+ ///
+ public static bool SupportsBool (this ObjectTypes types)
+ {
+ return (types & ObjectTypes.Bool) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectTypes.Number is set.
+ ///
+ public static bool SupportsNumber (this ObjectTypes types)
+ {
+ return (types & ObjectTypes.Number) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectTypes.Array is set.
+ ///
+ public static bool SupportsArray (this ObjectTypes types)
+ {
+ return (types & ObjectTypes.Array) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectTypes.Dictionary is set.
+ ///
+ public static bool SupportsDictionary (this ObjectTypes types)
+ {
+ return (types & ObjectTypes.Dictionary) != 0;
+ }
+
+ ///
+ /// Returns true if ObjectTypes.Custom is set.
+ ///
+ public static bool SupportsCustom (this ObjectTypes types)
+ {
+ return (types & ObjectTypes.Custom) != 0;
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/Enums.cs.meta b/Assets/Plugins/UnityJSON/Enums.cs.meta
new file mode 100644
index 0000000..f85e8d9
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Enums.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: aa9f64f7249024d36945056a36c0b401
+timeCreated: 1505381989
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/Interfaces.cs b/Assets/Plugins/UnityJSON/Interfaces.cs
new file mode 100644
index 0000000..9c7c9e9
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Interfaces.cs
@@ -0,0 +1,95 @@
+using SimpleJSON;
+using System;
+using System.Collections.Generic;
+
+namespace UnityJSON
+{
+ ///
+ /// Provides custom serialization for an object. If a
+ /// class or a struct inherits this interface, the serializer
+ /// simply calls this method to perform serialization. Please
+ /// notice that instances of ISerializable will not get
+ /// serialization lifecycle events even if they implement
+ /// ISerializationListener interface.
+ ///
+ public interface ISerializable
+ {
+ ///
+ /// Serializes the object into JSON string. You
+ /// can use the helper methods in the serializer.
+ ///
+ string Serialize (Serializer serializer);
+ }
+
+ ///
+ /// Provides custom deserialization for an object after it
+ /// is instantiated. You may still need to create your own
+ /// deserializer if your class / struct does not have a
+ /// constructor without parameters.
+ ///
+ /// If a class/struct inherits this interface, the deserializer
+ /// completely leaves the deserialization process to the
+ /// interface after the possible instantiation of the object.
+ /// Please notice that instances of IDeserializable will not get
+ /// deserialization lifecycle events even if they implement
+ /// IDeserializationListener interface.
+ ///
+ public interface IDeserializable
+ {
+ ///
+ /// Feeds the JSON node into the object. You can use the
+ /// helper methods from the deserializer.
+ ///
+ void Deserialize(JSONNode node, Deserializer deserializer);
+ }
+
+ ///
+ /// Listens for the serialization process on the object.
+ ///
+ public interface ISerializationListener
+ {
+ ///
+ /// Called just before the serialization of the object begins.
+ /// This call will always be followed by either OnSerializationSucceeded
+ /// or OnSerializationFailed but not both.
+ ///
+ void OnSerializationWillBegin(Serializer serializer);
+
+ ///
+ /// Called immediately after a successful completion of this
+ /// object's serialization.
+ ///
+ void OnSerializationSucceeded(Serializer serializer);
+
+ ///
+ /// Called when the serialization of the object fails for any
+ /// reason. This will be called just before throwing the exception.
+ ///
+ void OnSerializationFailed(Serializer serializer);
+ }
+
+ ///
+ /// Listens for the deserialization process on the object.
+ ///
+ public interface IDeserializationListener
+ {
+ ///
+ /// Called just before the deserialization of the object begins.
+ /// This call will always be followed by either OnDeserializationSucceeded
+ /// or OnDeserializationFailed but not both.
+ ///
+ void OnDeserializationWillBegin(Deserializer deserializer);
+
+ ///
+ /// Called immediately after a successful completion of this
+ /// object's deserialization.
+ ///
+ void OnDeserializationSucceeded(Deserializer deserializer);
+
+ ///
+ /// Called when the deserialization of the object fails for any
+ /// reason. This will be called just before throwing the exception.
+ ///
+ void OnDeserializationFailed(Deserializer deserializer);
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/Interfaces.cs.meta b/Assets/Plugins/UnityJSON/Interfaces.cs.meta
new file mode 100644
index 0000000..02b5c56
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Interfaces.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: de1b7a86fce434b98ba19932aee15cb3
+timeCreated: 1505462421
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/JSON.cs b/Assets/Plugins/UnityJSON/JSON.cs
new file mode 100644
index 0000000..8605035
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/JSON.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections;
+
+namespace UnityJSON
+{
+ ///
+ /// Provides high-level public API for the serialization and deserialization.
+ ///
+ public static class JSON
+ {
+ ///
+ /// Serializes the given object into JSON string. Throws an
+ /// error if the object is null.
+ ///
+ /// Object to be serialized.
+ /// Serialization options (optional).
+ /// Custom serializer. If not given,
+ /// the default serializer is used.
+ public static string Serialize (
+ object obj,
+ NodeOptions options = NodeOptions.Default,
+ Serializer serializer = null)
+ {
+ if (obj == null) {
+ throw new ArgumentNullException ("obj");
+ }
+ if (serializer == null) {
+ serializer = Serializer.Default;
+ }
+ return serializer.Serialize (obj, options);
+ }
+
+ ///
+ /// Serializes the object into JSON string.
+ ///
+ /// Object to be serialized.
+ /// Serialization options (optional).
+ /// Custom serializer. If not given,
+ /// the default serializer is used.
+ public static string ToJSONString (
+ this object obj,
+ NodeOptions options = NodeOptions.Default,
+ Serializer serializer = null)
+ {
+ return Serialize (obj, options, serializer);
+ }
+
+ ///
+ /// Deserializes an object of the generic type from
+ /// the given JSON string. Throws an exception if the string
+ /// is null or not a valid JSON string.
+ ///
+ /// The JSON string to deserialize from.
+ /// Deserialization options (optional).
+ /// Custom deserializer. If not given,
+ /// the default deserializer is used.
+ /// The type of object to deserialize.
+ public static T Deserialize (
+ string jsonString,
+ NodeOptions options = NodeOptions.Default,
+ Deserializer deserializer = null)
+ {
+ if (jsonString == null) {
+ throw new ArgumentNullException ("jsonString");
+ }
+ if (deserializer == null) {
+ deserializer = Deserializer.Default;
+ }
+
+ SimpleJSON.JSONNode node = SimpleJSON.JSON.Parse (jsonString);
+ if (node == null) {
+ throw new ArgumentException ("Argument is not a valid JSON string: " + jsonString);
+ }
+ return (T)deserializer.Deserialize (node, typeof(T), options);
+ }
+
+ ///
+ /// Deserializes a JSON string on a previously existing object.
+ /// Throws an exception if the string is null or not a valid JSON string.
+ ///
+ /// Object to deserialize on.
+ /// The JSON string to deserialize from.
+ /// Deserialization options (optional).
+ /// Custom deserializer. If not given,
+ /// the default deserializer is used.
+ public static void DeserializeOn (
+ object obj,
+ string jsonString,
+ NodeOptions options = NodeOptions.Default,
+ Deserializer deserializer = null)
+ {
+ if (obj == null) {
+ throw new ArgumentNullException ("obj");
+ }
+ if (jsonString == null) {
+ throw new ArgumentNullException ("jsonString");
+ }
+ if (deserializer == null) {
+ deserializer = Deserializer.Default;
+ }
+
+ SimpleJSON.JSONNode node = SimpleJSON.JSON.Parse (jsonString);
+ if (node == null) {
+ throw new ArgumentException ("Argument is not a valid JSON string: " + jsonString);
+ }
+ deserializer.DeserializeOn (obj, node, options);
+ }
+
+ ///
+ /// Deserializes a JSON string on the previously existing object.
+ /// Throws an exception if the string is null or not a valid JSON string.
+ ///
+ /// Object to deserialize on.
+ /// The JSON string to deserialize from.
+ /// Deserialization options (optional).
+ /// Custom deserializer. If not given,
+ /// the default deserializer is used.
+ public static void FeedJSON (
+ this object obj,
+ string jsonString,
+ NodeOptions options = NodeOptions.Default,
+ Deserializer deserializer = null)
+ {
+ DeserializeOn (obj, jsonString, options, deserializer);
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/JSON.cs.meta b/Assets/Plugins/UnityJSON/JSON.cs.meta
new file mode 100644
index 0000000..a87739e
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/JSON.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 79ef6b78ebc5d4f0fae7a1c5aa95cb0a
+timeCreated: 1505493113
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/Serializer.cs b/Assets/Plugins/UnityJSON/Serializer.cs
new file mode 100644
index 0000000..5a92777
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Serializer.cs
@@ -0,0 +1,487 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using UnityEngine;
+
+namespace UnityJSON
+{
+ ///
+ /// Serializes an object into JSON string. Subclasses should override
+ /// the #TrySerialize method.
+ ///
+ public class Serializer
+ {
+ private const string _kUndefined = "undefined";
+ private const string _kNull = "null";
+ private const string _kTrue = "true";
+ private const string _kFalse = "false";
+
+ private static Serializer _default = new Serializer ();
+ private static Serializer _simple = _default;
+
+ ///
+ /// The default serializer to be used when no serializer is given.
+ /// You can set this to your own default serializer. Uses the
+ /// #Simple serializer by default.
+ ///
+ public static Serializer Default {
+ get { return _default; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException ("default serializer");
+ }
+ _simple = value;
+ }
+ }
+
+ ///
+ /// The initial serializer that is provided by the framework.
+ ///
+ public static Serializer Simple {
+ get { return _simple; }
+ }
+
+ ///
+ /// When set to true, the keyword undefined is used instead of null
+ /// when serializing. Defaults to false.
+ ///
+ public bool useUndefinedForNull = false;
+
+ private Serializer()
+ {
+ }
+
+ ///
+ /// Tries to perform application-specific serialization. This is called
+ /// first when the #Serialize method is called, and performs internal
+ /// serialization if it returns false . This method is called before
+ /// ISerializable.Serialize.
+ ///
+ /// Object to serialize. Object is guaranteed to be non-null.
+ /// Serialization options.
+ /// The serialized JSON string.
+ protected virtual bool TrySerialize (
+ object obj,
+ NodeOptions options,
+ out string serialized)
+ {
+ serialized = null;
+ return false;
+ }
+
+ ///
+ /// Serializes any object into JSON string according to the given
+ /// options. This will first run through the #TrySerialize method and
+ /// then ISerializable.Serialize method if the object implements it.
+ /// If these are not implemented, then the framework serialization is
+ /// performed.
+ ///
+ public string Serialize (object obj, NodeOptions options = NodeOptions.Default)
+ {
+ if (obj == null) {
+ return SerializeNull (options);
+ }
+
+ string result = null;
+ if (TrySerialize (obj, options, out result)) {
+ return result;
+ }
+
+ ISerializable serializable = obj as ISerializable;
+ if (serializable != null) {
+ return serializable.Serialize (this);
+ }
+
+ if (obj != null) {
+ Type type = obj.GetType ();
+ if (type.IsValueType) {
+ if (type.IsEnum) {
+ result = _SerializeEnum ((Enum) obj);
+ } else if (type.IsPrimitive) {
+ if (obj is bool) {
+ result = SerializeBool ((bool)obj);
+ } else {
+ result = obj.ToString ();
+ }
+ } else {
+ if (obj is DictionaryEntry) {
+ result = _SerializeDictionaryEntry ((DictionaryEntry)obj, options);
+ } else if (obj is Vector2) {
+ result = SerializeVector2 ((Vector2)obj);
+ } else if (obj is Vector3) {
+ result = SerializeVector3 ((Vector3)obj);
+ } else if (obj is Vector4) {
+ result = SerializeVector4 ((Vector4)obj);
+ } else if (obj is Quaternion) {
+ result = SerializeQuaternion ((Quaternion)obj);
+ } else if (obj is Color) {
+ result = SerializeColor ((Color)obj);
+ } else if (obj is Rect) {
+ result = SerializeRect ((Rect)obj);
+ } else if (obj is Bounds) {
+ result = SerializeBounds ((Bounds)obj);
+ } else {
+ result = _SerializeCustom (obj, options);
+ }
+ }
+ } else {
+ if (obj is string) {
+ result = _SerializeString (obj as string);
+ } else if (Nullable.GetUnderlyingType (type) != null) {
+ result = _SerializeNullable (obj, options);
+ } else if (obj is IEnumerable) {
+ string enumerableJSON = _SerializeEnumarable (obj as IEnumerable, options);
+ if (obj is IDictionary) {
+ result = "{" + enumerableJSON + "}";
+ } else {
+ result = "[" + enumerableJSON + "]";
+ }
+ } else {
+ result = _SerializeCustom (obj, options);
+ }
+ }
+ }
+
+ if (result == null) {
+ return SerializeNull (options);
+ } else {
+ return result;
+ }
+ }
+
+ ///
+ /// Serializes null if NodeOptions.SerializeNull is used or
+ /// returns null otherwise. Null can be serialized as
+ /// "null" or "undefined" according to the value of #useUndefinedForNull.
+ ///
+ public string SerializeNull (NodeOptions options)
+ {
+ return options.ShouldSerializeNull () ?
+ (useUndefinedForNull ? _kUndefined : _kNull) : null;
+ }
+
+ ///
+ /// Serializes a string into JSON string with the optional
+ /// node options.
+ ///
+ public string SerializeString (
+ string stringValue,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (stringValue == null) {
+ return SerializeNull (options);
+ }
+ return _SerializeString (stringValue);
+ }
+
+ ///
+ /// Serializes an enum into JSON string. Throws ArgumentNullException
+ /// if the value is null .
+ ///
+ public string SerializeEnum (Enum enumValue)
+ {
+ if (enumValue == null) {
+ throw new ArgumentNullException ("enumValue");
+ }
+ return _SerializeEnum (enumValue);
+ }
+
+ ///
+ /// Serializes a System.Nullable object into JSON string.
+ /// Throws an ArgumentException if the object is not of a
+ /// nullable type.
+ ///
+ public string SerializeNullable (
+ object nullable,
+ NodeOptions options = NodeOptions.Default)
+ {
+ if (nullable == null) {
+ return SerializeNull (options);
+ }
+ if (Nullable.GetUnderlyingType (nullable.GetType ()) == null) {
+ throw new ArgumentException ("Argument is not a nullable object.");
+ }
+ return _SerializeNullable (nullable, options);
+ }
+
+ ///
+ /// Serializes a boolean value.
+ ///
+ public string SerializeBool (bool boolValue)
+ {
+ return boolValue ? _kTrue : _kFalse;
+ }
+
+ ///
+ /// Serializes Unity Vector2 into JSON string.
+ ///
+ public string SerializeVector2 (Vector2 vector)
+ {
+ return "{\"x\":" + vector.x + ",\"y\":" + vector.y + "}";
+ }
+
+ ///
+ /// Serializes Unity Vector3 into JSON string.
+ ///
+ public string SerializeVector3 (Vector3 vector)
+ {
+ return "{\"x\":" + vector.x + ",\"y\":" + vector.y + ",\"z\":" + vector.z + "}";
+ }
+
+ ///
+ /// Serializes Unity Vector4 into JSON string.
+ ///
+ public string SerializeVector4 (Vector4 vector)
+ {
+ return "{\"x\":" + vector.x + ",\"y\":" + vector.y
+ + ",\"z\":" + vector.z + ",\"w\":" + vector.w + "}";
+ }
+
+ ///
+ /// Serializes Unity Quaternion into JSON string.
+ ///
+ public string SerializeQuaternion (Quaternion quaternion)
+ {
+ return "{\"x\":" + quaternion.x + ",\"y\":" + quaternion.y
+ + ",\"z\":" + quaternion.z + ",\"w\":" + quaternion.w + "}";
+ }
+
+ ///
+ /// Serializes Unity Color into JSON string.
+ ///
+ public string SerializeColor (Color color)
+ {
+ return "{\"r\":" + color.r + ",\"g\":" + color.g
+ + ",\"b\":" + color.b + ",\"a\":" + color.a + "}";
+ }
+
+ ///
+ /// Serializes Unity Rect into JSON string.
+ ///
+ private string SerializeRect (Rect rect)
+ {
+ return "{\"x\":" + rect.x + ",\"y\":" + rect.y
+ + ",\"width\":" + rect.width + ",\"height\":" + rect.height + "}";
+ }
+
+ ///
+ /// Serializes Unity Bounds into JSON string.
+ ///
+ private string SerializeBounds (Bounds bounds)
+ {
+ return "{\"center\":" + SerializeVector3 (bounds.center)
+ + ",\"extents\":" + SerializeVector3 (bounds.extents) + "}";
+ }
+
+ private string _SerializeString (string stringValue)
+ {
+ return "\"" + stringValue.Replace ("\"", "\\\"") + "\"";
+ }
+
+ private string _SerializeEnum (Enum obj)
+ {
+ Type type = obj.GetType ();
+ JSONEnumAttribute enumAttribute = Util.GetAttribute (type);
+ if (enumAttribute != null) {
+ if (enumAttribute.useIntegers) {
+ return (Convert.ToInt32(obj)).ToString ();
+ } else {
+ string formatted = _FormatEnumMember (obj.ToString (), enumAttribute.format);
+ if (enumAttribute.prefix != null) {
+ formatted = enumAttribute.prefix + formatted;
+ }
+ if (enumAttribute.suffix != null) {
+ formatted += enumAttribute.suffix;
+ }
+ return _SerializeString (formatted);
+ }
+ } else {
+ return _SerializeString (obj.ToString ());
+ }
+ }
+
+ private string _SerializeNullable (object nullable, NodeOptions options)
+ {
+ Type type = nullable.GetType ();
+ if (!(bool)(type.GetProperty ("HasValue").GetValue (nullable, null))) {
+ return SerializeNull (options);
+ }
+
+ return Serialize (type.GetProperty ("Value").GetValue (nullable, null), options);
+ }
+
+ private string _SerializeEnumarable (IEnumerable enumerable, NodeOptions options)
+ {
+ if (enumerable is IList) {
+ // Always serialize nulls for arrays.
+ options |= NodeOptions.SerializeNull;
+ }
+ string joined = _Join (enumerable, obj => Serialize (obj, options));
+ if (joined == null) {
+ return SerializeNull (options);
+ } else {
+ return joined;
+ }
+ }
+
+ private string _SerializeDictionaryEntry (DictionaryEntry entry, NodeOptions options)
+ {
+ // Don't serialize nulls for keys. If a key is null, its pair
+ // shouldn't be serialized as undefined:value.
+ NodeOptions keyOptions = options & ~NodeOptions.SerializeNull;
+ string serializedKey = Serialize (entry.Key, keyOptions);
+ if (serializedKey == null) {
+ return SerializeNull (options);
+ }
+
+ string valueKey = Serialize (entry.Value, options);
+ if (valueKey == null) {
+ return null;
+ } else {
+ string jsonKey = entry.Key is string ? serializedKey : _SerializeString (serializedKey);
+ return jsonKey + ":" + valueKey;
+ }
+ }
+
+ private string _SerializeCustom (object obj, NodeOptions options)
+ {
+ ISerializationListener listener = obj as ISerializationListener;
+ if (listener != null) {
+ listener.OnSerializationWillBegin (this);
+ }
+
+ try {
+ IEnumerable enumerable = new string[] { };
+ MemberInfo extrasMember = null;
+ JSONExtrasAttribute extrasAttribute = null;
+
+ // Find member info and attribute for extras while going over the
+ // fields and properties.
+ Func isNotExtras = m => {
+ if (extrasMember == null && Util.IsJSONExtrasMember (m, out extrasAttribute)) {
+ extrasMember = m;
+ return false;
+ } else {
+ return true;
+ }
+ };
+
+ Type type = obj.GetType ();
+ JSONObjectAttribute classAttribute = Util.GetAttribute (type);
+ var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+ if (classAttribute != null && !classAttribute.options.ShouldIgnoreStatic ()) {
+ flags |= BindingFlags.Static;
+ }
+
+ enumerable = enumerable.Concat (
+ from f in type.GetFields (flags)
+ where isNotExtras (f) && _IsValidFieldInfo (f)
+ select _SerializeCustomField (obj, f));
+
+ if (classAttribute == null || !classAttribute.options.ShouldIgnoreProperties ()) {
+ enumerable = enumerable.Concat (
+ from p in type.GetProperties (flags)
+ where isNotExtras (p) && _IsValidPropertyInfo (p)
+ select _SerializeCustomProperty (obj, p));
+ }
+
+ // Serialize all properties and fields.
+ var result = _Join (enumerable, o => o as string);
+
+ // Serialize the extras if there are any.
+ if (extrasMember != null) {
+ var extras = Util.GetMemberValue (extrasMember, obj) as IEnumerable;
+ if (extras != null) {
+ result += (result == "" ? "" : ",")
+ + _SerializeEnumarable (extras, extrasAttribute.options);
+ }
+ }
+
+ if (listener != null) {
+ listener.OnSerializationSucceeded (this);
+ }
+ return "{" + result + "}";;
+ } catch (Exception exception) {
+ if (listener != null) {
+ listener.OnSerializationFailed (this);
+ }
+ throw exception;
+ }
+ }
+
+ private bool _IsValidFieldInfo (FieldInfo fieldInfo)
+ {
+ return fieldInfo.IsPublic || Attribute.IsDefined (fieldInfo, typeof(JSONNodeAttribute), true);
+ }
+
+ private bool _IsValidPropertyInfo (PropertyInfo propertyInfo)
+ {
+ return propertyInfo.GetIndexParameters ().Length == 0 && propertyInfo.CanRead &&
+ (propertyInfo.GetGetMethod (false) != null ||
+ Attribute.IsDefined (propertyInfo, typeof(JSONNodeAttribute), true));
+ }
+
+ private string _FormatEnumMember (string member, JSONEnumMemberFormating format)
+ {
+ switch (format) {
+ case JSONEnumMemberFormating.Lowercased:
+ return member.ToLower ();
+ case JSONEnumMemberFormating.Uppercased:
+ return member.ToUpper ();
+ case JSONEnumMemberFormating.Capitalized:
+ return Char.ToUpper (member [0]) + member.Substring (1).ToLower ();
+ default:
+ return member;
+ }
+ }
+
+ private string _Join (IEnumerable enumerable, Func serializer)
+ {
+ string result = "";
+ bool firstAdded = false;
+
+ IEnumerator enumerator = enumerable is IDictionary ?
+ (enumerable as IDictionary).GetEnumerator () :
+ enumerable.GetEnumerator ();
+
+ while (enumerator.MoveNext ()) {
+ string serialized = serializer (enumerator.Current);
+ if (serialized != null) {
+ string prefix = firstAdded ? "," : "";
+ firstAdded = true;
+ result += prefix + serialized;
+ }
+ }
+ return result;
+ }
+
+ private string _SerializeCustomField (object obj, FieldInfo fieldInfo)
+ {
+ return _SerializeCustomMember (fieldInfo, fieldInfo.GetValue (obj));
+ }
+
+ private string _SerializeCustomProperty (object obj, PropertyInfo propertyInfo)
+ {
+ return _SerializeCustomMember (propertyInfo, propertyInfo.GetValue (obj, null));
+ }
+
+ private string _SerializeCustomMember (MemberInfo keyMemberInfo, object value)
+ {
+ JSONNodeAttribute attribute = Util.GetAttribute (keyMemberInfo);
+ NodeOptions options = attribute == null ? NodeOptions.Default : attribute.options;
+ if (!options.IsSerialized ()) {
+ return null;
+ }
+
+ string valueString = Serialize (value, options);
+ if (valueString != null || options.ShouldSerializeNull ()) {
+ string key = (attribute != null && attribute.key != null) ? attribute.key : keyMemberInfo.Name;
+ return _SerializeString (key) + ":" + (valueString == null ? _kUndefined : valueString);
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/Serializer.cs.meta b/Assets/Plugins/UnityJSON/Serializer.cs.meta
new file mode 100644
index 0000000..75a902b
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Serializer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 50efb33f1602f4d9197ef073f1b025c5
+timeCreated: 1505244340
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/SimpleJSON.cs b/Assets/Plugins/UnityJSON/SimpleJSON.cs
new file mode 100644
index 0000000..38872a1
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/SimpleJSON.cs
@@ -0,0 +1,1432 @@
+//#define USE_SharpZipLib
+#if !UNITY_WEBPLAYER
+#define USE_FileIO
+#endif
+/* * * * *
+ * A simple JSON Parser / builder
+ * ------------------------------
+ *
+ * It mainly has been written as a simple JSON parser. It can build a JSON string
+ * from the node-tree, or generate a node tree from any valid JSON string.
+ *
+ * If you want to use compression when saving to file / stream / B64 you have to include
+ * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
+ * define "USE_SharpZipLib" at the top of the file
+ *
+ * Written by Bunny83
+ * 2012-06-09
+ *
+ *
+ * Features / attributes:
+ * - provides strongly typed node classes and lists / dictionaries
+ * - provides easy access to class members / array items / data values
+ * - the parser now properly identifies types. So generating JSON with this framework should work.
+ * - only double quotes (") are used for quoting strings.
+ * - provides "casting" properties to easily convert to / from those types:
+ * int / float / double / bool
+ * - provides a common interface for each node so no explicit casting is required.
+ * - the parser tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined
+ * - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might
+ * be handy if you want to store things in a file and don't want it to be easily modifiable
+ *
+ *
+ * 2012-12-17 Update:
+ * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
+ * Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
+ * The class determines the required type by it's further use, creates the type and removes itself.
+ * - Added binary serialization / deserialization.
+ * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
+ * The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
+ * - The serializer uses different types when it comes to store the values. Since my data values
+ * are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
+ * It's not the most efficient way but for a moderate amount of data it should work on all platforms.
+ *
+ * 2017-03-08 Update:
+ * - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large
+ * string data fields are contained in the json data.
+ * - Finally refactored the badly named JSONClass into JSONObject.
+ * - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this
+ * allows to propertly convert the node tree back to json without type information loss. The actual value
+ * parsing now happens at parsing time and not when you actually access one of the casting properties.
+ *
+ * 2017-04-11 Update:
+ * - Fixed parsing bug where empty string values have been ignored.
+ * - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files
+ * - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)"
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2017 Markus Göbel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * * * * */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SimpleJSON
+{
+ public enum JSONNodeType
+ {
+ Array = 1,
+ Object = 2,
+ String = 3,
+ Number = 4,
+ NullValue = 5,
+ Boolean = 6,
+ None = 7,
+ }
+ public enum JSONTextMode
+ {
+ Compact,
+ Indent
+ }
+
+ public abstract partial class JSONNode
+ {
+ #region common interface
+
+ public virtual JSONNode this[int aIndex] { get { return null; } set { } }
+
+ public virtual JSONNode this[string aKey] { get { return null; } set { } }
+
+ public virtual string Value { get { return ""; } set { } }
+
+ public virtual int Count { get { return 0; } }
+
+ public virtual bool IsNumber { get { return false; } }
+ public virtual bool IsString { get { return false; } }
+ public virtual bool IsBoolean { get { return false; } }
+ public virtual bool IsNull { get { return false; } }
+ public virtual bool IsArray { get { return false; } }
+ public virtual bool IsObject { get { return false; } }
+
+ public virtual void Add(string aKey, JSONNode aItem)
+ {
+ }
+ public virtual void Add(JSONNode aItem)
+ {
+ Add("", aItem);
+ }
+
+ public virtual JSONNode Remove(string aKey)
+ {
+ return null;
+ }
+
+ public virtual JSONNode Remove(int aIndex)
+ {
+ return null;
+ }
+
+ public virtual JSONNode Remove(JSONNode aNode)
+ {
+ return aNode;
+ }
+
+ public virtual IEnumerable Children
+ {
+ get
+ {
+ yield break;
+ }
+ }
+
+ public IEnumerable DeepChildren
+ {
+ get
+ {
+ foreach (var C in Children)
+ foreach (var D in C.DeepChildren)
+ yield return D;
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact);
+ return sb.ToString();
+ }
+
+ public virtual string ToString(int aIndent)
+ {
+ StringBuilder sb = new StringBuilder();
+ WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent);
+ return sb.ToString();
+ }
+ internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);
+
+ #endregion common interface
+
+ #region typecasting properties
+
+ public abstract JSONNodeType Tag { get; }
+
+ public virtual double AsDouble
+ {
+ get
+ {
+ double v = 0.0;
+ if (double.TryParse(Value, out v))
+ return v;
+ return 0.0;
+ }
+ set
+ {
+ Value = value.ToString();
+ }
+ }
+
+ public virtual int AsInt
+ {
+ get { return (int)AsDouble; }
+ set { AsDouble = value; }
+ }
+
+ public virtual float AsFloat
+ {
+ get { return (float)AsDouble; }
+ set { AsDouble = value; }
+ }
+
+ public virtual bool AsBool
+ {
+ get
+ {
+ bool v = false;
+ if (bool.TryParse(Value, out v))
+ return v;
+ return !string.IsNullOrEmpty(Value);
+ }
+ set
+ {
+ Value = (value) ? "true" : "false";
+ }
+ }
+
+ public virtual JSONArray AsArray
+ {
+ get
+ {
+ return this as JSONArray;
+ }
+ }
+
+ public virtual JSONObject AsObject
+ {
+ get
+ {
+ return this as JSONObject;
+ }
+ }
+
+
+ #endregion typecasting properties
+
+ #region operators
+
+ public static implicit operator JSONNode(string s)
+ {
+ return new JSONString(s);
+ }
+ public static implicit operator string(JSONNode d)
+ {
+ return (d == null) ? null : d.Value;
+ }
+
+ public static implicit operator JSONNode(double n)
+ {
+ return new JSONNumber(n);
+ }
+ public static implicit operator double(JSONNode d)
+ {
+ return (d == null) ? 0 : d.AsDouble;
+ }
+
+ public static implicit operator JSONNode(float n)
+ {
+ return new JSONNumber(n);
+ }
+ public static implicit operator float(JSONNode d)
+ {
+ return (d == null) ? 0 : d.AsFloat;
+ }
+
+ public static implicit operator JSONNode(int n)
+ {
+ return new JSONNumber(n);
+ }
+ public static implicit operator int(JSONNode d)
+ {
+ return (d == null) ? 0 : d.AsInt;
+ }
+
+ public static implicit operator JSONNode(bool b)
+ {
+ return new JSONBool(b);
+ }
+ public static implicit operator bool(JSONNode d)
+ {
+ return (d == null) ? false : d.AsBool;
+ }
+
+ public static bool operator ==(JSONNode a, object b)
+ {
+ if (ReferenceEquals(a, b))
+ return true;
+ bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator;
+ bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator;
+ if (aIsNull && bIsNull)
+ return true;
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(JSONNode a, object b)
+ {
+ return !(a == b);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #endregion operators
+ internal static StringBuilder m_EscapeBuilder = new StringBuilder();
+ internal static string Escape(string aText)
+ {
+ m_EscapeBuilder.Length = 0;
+ if (m_EscapeBuilder.Capacity < aText.Length + aText.Length / 10)
+ m_EscapeBuilder.Capacity = aText.Length + aText.Length / 10;
+ foreach (char c in aText)
+ {
+ switch (c)
+ {
+ case '\\':
+ m_EscapeBuilder.Append("\\\\");
+ break;
+ case '\"':
+ m_EscapeBuilder.Append("\\\"");
+ break;
+ case '\n':
+ m_EscapeBuilder.Append("\\n");
+ break;
+ case '\r':
+ m_EscapeBuilder.Append("\\r");
+ break;
+ case '\t':
+ m_EscapeBuilder.Append("\\t");
+ break;
+ case '\b':
+ m_EscapeBuilder.Append("\\b");
+ break;
+ case '\f':
+ m_EscapeBuilder.Append("\\f");
+ break;
+ default:
+ m_EscapeBuilder.Append(c);
+ break;
+ }
+ }
+ string result = m_EscapeBuilder.ToString();
+ m_EscapeBuilder.Length = 0;
+ return result;
+ }
+
+ static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted)
+ {
+ if (quoted)
+ {
+ ctx.Add(tokenName, token);
+ return;
+ }
+ string tmp = token.ToLower();
+ if (tmp == "false" || tmp == "true")
+ ctx.Add(tokenName, tmp == "true");
+ else if (tmp == "null")
+ ctx.Add(tokenName, null);
+ else if (tmp == "undefined")
+ ctx.Add(tokenName, null);
+ else
+ {
+ double val;
+ if (double.TryParse(token, out val))
+ ctx.Add(tokenName, val);
+ else
+ ctx.Add(tokenName, token);
+ }
+ }
+
+ public static JSONNode Parse(string aJSON)
+ {
+ Stack stack = new Stack();
+ JSONNode ctx = null;
+ int i = 0;
+ StringBuilder Token = new StringBuilder();
+ string TokenName = "";
+ bool QuoteMode = false;
+ bool TokenIsQuoted = false;
+ while (i < aJSON.Length)
+ {
+ switch (aJSON[i])
+ {
+ case '{':
+ if (QuoteMode)
+ {
+ Token.Append(aJSON[i]);
+ break;
+ }
+ stack.Push(new JSONObject());
+ if (ctx != null)
+ {
+ ctx.Add(TokenName, stack.Peek());
+ }
+ TokenName = "";
+ Token.Length = 0;
+ ctx = stack.Peek();
+ break;
+
+ case '[':
+ if (QuoteMode)
+ {
+ Token.Append(aJSON[i]);
+ break;
+ }
+
+ stack.Push(new JSONArray());
+ if (ctx != null)
+ {
+ ctx.Add(TokenName, stack.Peek());
+ }
+ TokenName = "";
+ Token.Length = 0;
+ ctx = stack.Peek();
+ break;
+
+ case '}':
+ case ']':
+ if (QuoteMode)
+ {
+
+ Token.Append(aJSON[i]);
+ break;
+ }
+ if (stack.Count == 0)
+ throw new Exception("JSON Parse: Too many closing brackets");
+
+ stack.Pop();
+ if (Token.Length > 0 || TokenIsQuoted)
+ {
+ ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted);
+ TokenIsQuoted = false;
+ }
+ TokenName = "";
+ Token.Length = 0;
+ if (stack.Count > 0)
+ ctx = stack.Peek();
+ break;
+
+ case ':':
+ if (QuoteMode)
+ {
+ Token.Append(aJSON[i]);
+ break;
+ }
+ TokenName = Token.ToString();
+ Token.Length = 0;
+ TokenIsQuoted = false;
+ break;
+
+ case '"':
+ QuoteMode ^= true;
+ TokenIsQuoted |= QuoteMode;
+ break;
+
+ case ',':
+ if (QuoteMode)
+ {
+ Token.Append(aJSON[i]);
+ break;
+ }
+ if (Token.Length > 0 || TokenIsQuoted)
+ {
+ ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted);
+ TokenIsQuoted = false;
+ }
+ TokenName = "";
+ Token.Length = 0;
+ TokenIsQuoted = false;
+ break;
+
+ case '\r':
+ case '\n':
+ break;
+
+ case ' ':
+ case '\t':
+ if (QuoteMode)
+ Token.Append(aJSON[i]);
+ break;
+
+ case '\\':
+ ++i;
+ if (QuoteMode)
+ {
+ char C = aJSON[i];
+ switch (C)
+ {
+ case 't':
+ Token.Append('\t');
+ break;
+ case 'r':
+ Token.Append('\r');
+ break;
+ case 'n':
+ Token.Append('\n');
+ break;
+ case 'b':
+ Token.Append('\b');
+ break;
+ case 'f':
+ Token.Append('\f');
+ break;
+ case 'u':
+ {
+ string s = aJSON.Substring(i + 1, 4);
+ Token.Append((char)int.Parse(
+ s,
+ System.Globalization.NumberStyles.AllowHexSpecifier));
+ i += 4;
+ break;
+ }
+ default:
+ Token.Append(C);
+ break;
+ }
+ }
+ break;
+
+ default:
+ Token.Append(aJSON[i]);
+ break;
+ }
+ ++i;
+ }
+ if (QuoteMode)
+ {
+ throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
+ }
+ return ctx;
+ }
+
+ public virtual void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ }
+
+ public void SaveToStream(System.IO.Stream aData)
+ {
+ var W = new System.IO.BinaryWriter(aData);
+ Serialize(W);
+ }
+
+ #if USE_SharpZipLib
+ public void SaveToCompressedStream(System.IO.Stream aData)
+ {
+ using (var gzipOut = new ICSharpCode.SharpZipLib.BZip2.BZip2OutputStream(aData))
+ {
+ gzipOut.IsStreamOwner = false;
+ SaveToStream(gzipOut);
+ gzipOut.Close();
+ }
+ }
+
+ public void SaveToCompressedFile(string aFileName)
+ {
+
+ #if USE_FileIO
+ System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
+ using(var F = System.IO.File.OpenWrite(aFileName))
+ {
+ SaveToCompressedStream(F);
+ }
+
+ #else
+ throw new Exception("Can't use File IO stuff in the webplayer");
+ #endif
+ }
+ public string SaveToCompressedBase64()
+ {
+ using (var stream = new System.IO.MemoryStream())
+ {
+ SaveToCompressedStream(stream);
+ stream.Position = 0;
+ return System.Convert.ToBase64String(stream.ToArray());
+ }
+ }
+
+ #else
+ public void SaveToCompressedStream(System.IO.Stream aData)
+ {
+ throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+ }
+
+ public void SaveToCompressedFile(string aFileName)
+ {
+ throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+ }
+
+ public string SaveToCompressedBase64()
+ {
+ throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+ }
+ #endif
+
+ public void SaveToFile(string aFileName)
+ {
+ #if USE_FileIO
+ System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
+ using (var F = System.IO.File.OpenWrite(aFileName))
+ {
+ SaveToStream(F);
+ }
+ #else
+ throw new Exception ("Can't use File IO stuff in the webplayer");
+ #endif
+ }
+
+ public string SaveToBase64()
+ {
+ using (var stream = new System.IO.MemoryStream())
+ {
+ SaveToStream(stream);
+ stream.Position = 0;
+ return System.Convert.ToBase64String(stream.ToArray());
+ }
+ }
+
+ public static JSONNode Deserialize(System.IO.BinaryReader aReader)
+ {
+ JSONNodeType type = (JSONNodeType)aReader.ReadByte();
+ switch (type)
+ {
+ case JSONNodeType.Array:
+ {
+ int count = aReader.ReadInt32();
+ JSONArray tmp = new JSONArray();
+ for (int i = 0; i < count; i++)
+ tmp.Add(Deserialize(aReader));
+ return tmp;
+ }
+ case JSONNodeType.Object:
+ {
+ int count = aReader.ReadInt32();
+ JSONObject tmp = new JSONObject();
+ for (int i = 0; i < count; i++)
+ {
+ string key = aReader.ReadString();
+ var val = Deserialize(aReader);
+ tmp.Add(key, val);
+ }
+ return tmp;
+ }
+ case JSONNodeType.String:
+ {
+ return new JSONString(aReader.ReadString());
+ }
+ case JSONNodeType.Number:
+ {
+ return new JSONNumber(aReader.ReadDouble());
+ }
+ case JSONNodeType.Boolean:
+ {
+ return new JSONBool(aReader.ReadBoolean());
+ }
+ case JSONNodeType.NullValue:
+ {
+ return new JSONNull();
+ }
+ default:
+ {
+ throw new Exception("Error deserializing JSON. Unknown tag: " + type);
+ }
+ }
+ }
+
+ #if USE_SharpZipLib
+ public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
+ {
+ var zin = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(aData);
+ return LoadFromStream(zin);
+ }
+ public static JSONNode LoadFromCompressedFile(string aFileName)
+ {
+ #if USE_FileIO
+ using(var F = System.IO.File.OpenRead(aFileName))
+ {
+ return LoadFromCompressedStream(F);
+ }
+ #else
+ throw new Exception("Can't use File IO stuff in the webplayer");
+ #endif
+ }
+ public static JSONNode LoadFromCompressedBase64(string aBase64)
+ {
+ var tmp = System.Convert.FromBase64String(aBase64);
+ var stream = new System.IO.MemoryStream(tmp);
+ stream.Position = 0;
+ return LoadFromCompressedStream(stream);
+ }
+ #else
+ public static JSONNode LoadFromCompressedFile(string aFileName)
+ {
+ throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+ }
+
+ public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
+ {
+ throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+ }
+
+ public static JSONNode LoadFromCompressedBase64(string aBase64)
+ {
+ throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
+ }
+ #endif
+
+ public static JSONNode LoadFromStream(System.IO.Stream aData)
+ {
+ using (var R = new System.IO.BinaryReader(aData))
+ {
+ return Deserialize(R);
+ }
+ }
+
+ public static JSONNode LoadFromFile(string aFileName)
+ {
+ #if USE_FileIO
+ using (var F = System.IO.File.OpenRead(aFileName))
+ {
+ return LoadFromStream(F);
+ }
+ #else
+ throw new Exception ("Can't use File IO stuff in the webplayer");
+ #endif
+ }
+
+ public static JSONNode LoadFromBase64(string aBase64)
+ {
+ var tmp = System.Convert.FromBase64String(aBase64);
+ var stream = new System.IO.MemoryStream(tmp);
+ stream.Position = 0;
+ return LoadFromStream(stream);
+ }
+ }
+ // End of JSONNode
+
+ public class JSONArray : JSONNode, IEnumerable
+ {
+ private List m_List = new List();
+ public bool inline = false;
+
+ public override JSONNodeType Tag { get { return JSONNodeType.Array; } }
+ public override bool IsArray { get { return true; } }
+
+ public override JSONNode this[int aIndex]
+ {
+ get
+ {
+ if (aIndex < 0 || aIndex >= m_List.Count)
+ return new JSONLazyCreator(this);
+ return m_List[aIndex];
+ }
+ set
+ {
+ if (value == null)
+ value = new JSONNull();
+ if (aIndex < 0 || aIndex >= m_List.Count)
+ m_List.Add(value);
+ else
+ m_List[aIndex] = value;
+ }
+ }
+
+ public override JSONNode this[string aKey]
+ {
+ get { return new JSONLazyCreator(this); }
+ set
+ {
+ if (value == null)
+ value = new JSONNull();
+ m_List.Add(value);
+ }
+ }
+
+ public override int Count
+ {
+ get { return m_List.Count; }
+ }
+
+ public override void Add(string aKey, JSONNode aItem)
+ {
+ if (aItem == null)
+ aItem = new JSONNull();
+ m_List.Add(aItem);
+ }
+
+ public override JSONNode Remove(int aIndex)
+ {
+ if (aIndex < 0 || aIndex >= m_List.Count)
+ return null;
+ JSONNode tmp = m_List[aIndex];
+ m_List.RemoveAt(aIndex);
+ return tmp;
+ }
+
+ public override JSONNode Remove(JSONNode aNode)
+ {
+ m_List.Remove(aNode);
+ return aNode;
+ }
+
+ public override IEnumerable Children
+ {
+ get
+ {
+ foreach (JSONNode N in m_List)
+ yield return N;
+ }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach (JSONNode N in m_List)
+ yield return N;
+ }
+
+ public override void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ aWriter.Write((byte)JSONNodeType.Array);
+ aWriter.Write(m_List.Count);
+ for (int i = 0; i < m_List.Count; i++)
+ {
+ m_List[i].Serialize(aWriter);
+ }
+ }
+
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append('[');
+ int count = m_List.Count;
+ if (inline)
+ aMode = JSONTextMode.Compact;
+ for (int i = 0; i < count; i++)
+ {
+ if (i > 0)
+ aSB.Append(',');
+ if (aMode == JSONTextMode.Indent)
+ aSB.AppendLine();
+
+ if (aMode == JSONTextMode.Indent)
+ aSB.Append(' ', aIndent + aIndentInc);
+ m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
+ }
+ if (aMode == JSONTextMode.Indent)
+ aSB.AppendLine().Append(' ', aIndent);
+ aSB.Append(']');
+ }
+ }
+ // End of JSONArray
+
+ public class JSONObject : JSONNode, IEnumerable
+ {
+ private Dictionary m_Dict = new Dictionary();
+
+ public bool inline = false;
+
+ public override JSONNodeType Tag { get { return JSONNodeType.Object; } }
+ public override bool IsObject { get { return true; } }
+
+
+ public override JSONNode this[string aKey]
+ {
+ get
+ {
+ if (m_Dict.ContainsKey(aKey))
+ return m_Dict[aKey];
+ else
+ return new JSONLazyCreator(this, aKey);
+ }
+ set
+ {
+ if (value == null)
+ value = new JSONNull();
+ if (m_Dict.ContainsKey(aKey))
+ m_Dict[aKey] = value;
+ else
+ m_Dict.Add(aKey, value);
+ }
+ }
+
+ public override JSONNode this[int aIndex]
+ {
+ get
+ {
+ if (aIndex < 0 || aIndex >= m_Dict.Count)
+ return null;
+ return m_Dict.ElementAt(aIndex).Value;
+ }
+ set
+ {
+ if (value == null)
+ value = new JSONNull();
+ if (aIndex < 0 || aIndex >= m_Dict.Count)
+ return;
+ string key = m_Dict.ElementAt(aIndex).Key;
+ m_Dict[key] = value;
+ }
+ }
+
+ public override int Count
+ {
+ get { return m_Dict.Count; }
+ }
+
+ public override void Add(string aKey, JSONNode aItem)
+ {
+ if (aItem == null)
+ aItem = new JSONNull();
+
+ if (!string.IsNullOrEmpty(aKey))
+ {
+ if (m_Dict.ContainsKey(aKey))
+ m_Dict[aKey] = aItem;
+ else
+ m_Dict.Add(aKey, aItem);
+ }
+ else
+ m_Dict.Add(Guid.NewGuid().ToString(), aItem);
+ }
+
+ public override JSONNode Remove(string aKey)
+ {
+ if (!m_Dict.ContainsKey(aKey))
+ return null;
+ JSONNode tmp = m_Dict[aKey];
+ m_Dict.Remove(aKey);
+ return tmp;
+ }
+
+ public override JSONNode Remove(int aIndex)
+ {
+ if (aIndex < 0 || aIndex >= m_Dict.Count)
+ return null;
+ var item = m_Dict.ElementAt(aIndex);
+ m_Dict.Remove(item.Key);
+ return item.Value;
+ }
+
+ public override JSONNode Remove(JSONNode aNode)
+ {
+ try
+ {
+ var item = m_Dict.Where(k => k.Value == aNode).First();
+ m_Dict.Remove(item.Key);
+ return aNode;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public override IEnumerable Children
+ {
+ get
+ {
+ foreach (KeyValuePair N in m_Dict)
+ yield return N.Value;
+ }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach (KeyValuePair N in m_Dict)
+ yield return N;
+ }
+
+ public override void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ aWriter.Write((byte)JSONNodeType.Object);
+ aWriter.Write(m_Dict.Count);
+ foreach (string K in m_Dict.Keys)
+ {
+ aWriter.Write(K);
+ m_Dict[K].Serialize(aWriter);
+ }
+ }
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append('{');
+ bool first = true;
+ if (inline)
+ aMode = JSONTextMode.Compact;
+ foreach (var k in m_Dict)
+ {
+ if (!first)
+ aSB.Append(',');
+ first = false;
+ if (aMode == JSONTextMode.Indent)
+ aSB.AppendLine();
+ if (aMode == JSONTextMode.Indent)
+ aSB.Append(' ', aIndent + aIndentInc);
+ aSB.Append('\"').Append(Escape(k.Key)).Append('\"');
+ if (aMode == JSONTextMode.Compact)
+ aSB.Append(':');
+ else
+ aSB.Append(" : ");
+ k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
+ }
+ if (aMode == JSONTextMode.Indent)
+ aSB.AppendLine().Append(' ', aIndent);
+ aSB.Append('}');
+ }
+
+ }
+ // End of JSONObject
+
+ public class JSONString : JSONNode
+ {
+ private string m_Data;
+
+ public override JSONNodeType Tag { get { return JSONNodeType.String; } }
+ public override bool IsString { get { return true; } }
+
+ public override string Value
+ {
+ get { return m_Data; }
+ set
+ {
+ m_Data = value;
+ }
+ }
+
+ public JSONString(string aData)
+ {
+ m_Data = aData;
+ }
+
+ public override void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ aWriter.Write((byte)JSONNodeType.String);
+ aWriter.Write(m_Data);
+ }
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append('\"').Append(Escape(m_Data)).Append('\"');
+ }
+ public override bool Equals(object obj)
+ {
+ if (base.Equals(obj))
+ return true;
+ string s = obj as string;
+ if (s != null)
+ return m_Data == s;
+ JSONString s2 = obj as JSONString;
+ if (s2 != null)
+ return m_Data == s2.m_Data;
+ return false;
+ }
+ public override int GetHashCode()
+ {
+ return m_Data.GetHashCode();
+ }
+ }
+ // End of JSONString
+
+ public class JSONNumber : JSONNode
+ {
+ private double m_Data;
+
+ public override JSONNodeType Tag { get { return JSONNodeType.Number; } }
+ public override bool IsNumber { get { return true; } }
+
+
+ public override string Value
+ {
+ get { return m_Data.ToString(); }
+ set
+ {
+ double v;
+ if (double.TryParse(value, out v))
+ m_Data = v;
+ }
+ }
+
+ public override double AsDouble
+ {
+ get { return m_Data; }
+ set { m_Data = value; }
+ }
+
+ public JSONNumber(double aData)
+ {
+ m_Data = aData;
+ }
+
+ public JSONNumber(string aData)
+ {
+ Value = aData;
+ }
+
+ public override void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ aWriter.Write((byte)JSONNodeType.Number);
+ aWriter.Write(m_Data);
+ }
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append(m_Data);
+ }
+ private static bool IsNumeric(object value)
+ {
+ return value is int || value is uint
+ || value is float || value is double
+ || value is decimal
+ || value is long || value is ulong
+ || value is short || value is ushort
+ || value is sbyte || value is byte;
+ }
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+ if (base.Equals(obj))
+ return true;
+ JSONNumber s2 = obj as JSONNumber;
+ if (s2 != null)
+ return m_Data == s2.m_Data;
+ if (IsNumeric(obj))
+ return Convert.ToDouble(obj) == m_Data;
+ return false;
+ }
+ public override int GetHashCode()
+ {
+ return m_Data.GetHashCode();
+ }
+ }
+ // End of JSONNumber
+
+ public class JSONBool : JSONNode
+ {
+ private bool m_Data;
+
+ public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } }
+ public override bool IsBoolean { get { return true; } }
+
+
+ public override string Value
+ {
+ get { return m_Data.ToString(); }
+ set
+ {
+ bool v;
+ if (bool.TryParse(value, out v))
+ m_Data = v;
+ }
+ }
+ public override bool AsBool
+ {
+ get { return m_Data; }
+ set { m_Data = value; }
+ }
+
+ public JSONBool(bool aData)
+ {
+ m_Data = aData;
+ }
+
+ public JSONBool(string aData)
+ {
+ Value = aData;
+ }
+
+ public override void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ aWriter.Write((byte)JSONNodeType.Boolean);
+ aWriter.Write(m_Data);
+ }
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append((m_Data) ? "true" : "false");
+ }
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+ if (obj is bool)
+ return m_Data == (bool)obj;
+ return false;
+ }
+ public override int GetHashCode()
+ {
+ return m_Data.GetHashCode();
+ }
+ }
+ // End of JSONBool
+
+ public class JSONNull : JSONNode
+ {
+
+ public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } }
+ public override bool IsNull { get { return true; } }
+
+ public override string Value
+ {
+ get { return "null"; }
+ set { }
+ }
+ public override bool AsBool
+ {
+ get { return false; }
+ set { }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (object.ReferenceEquals(this, obj))
+ return true;
+ return (obj is JSONNull);
+ }
+ public override int GetHashCode()
+ {
+ return 0;
+ }
+
+ public override void Serialize(System.IO.BinaryWriter aWriter)
+ {
+ aWriter.Write((byte)JSONNodeType.NullValue);
+ }
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append("null");
+ }
+ }
+ // End of JSONNull
+
+ internal class JSONLazyCreator : JSONNode
+ {
+ private JSONNode m_Node = null;
+ private string m_Key = null;
+
+ public override JSONNodeType Tag { get { return JSONNodeType.None; } }
+
+ public JSONLazyCreator(JSONNode aNode)
+ {
+ m_Node = aNode;
+ m_Key = null;
+ }
+
+ public JSONLazyCreator(JSONNode aNode, string aKey)
+ {
+ m_Node = aNode;
+ m_Key = aKey;
+ }
+
+ private void Set(JSONNode aVal)
+ {
+ if (m_Key == null)
+ {
+ m_Node.Add(aVal);
+ }
+ else
+ {
+ m_Node.Add(m_Key, aVal);
+ }
+ m_Node = null; // Be GC friendly.
+ }
+
+ public override JSONNode this[int aIndex]
+ {
+ get
+ {
+ return new JSONLazyCreator(this);
+ }
+ set
+ {
+ var tmp = new JSONArray();
+ tmp.Add(value);
+ Set(tmp);
+ }
+ }
+
+ public override JSONNode this[string aKey]
+ {
+ get
+ {
+ return new JSONLazyCreator(this, aKey);
+ }
+ set
+ {
+ var tmp = new JSONObject();
+ tmp.Add(aKey, value);
+ Set(tmp);
+ }
+ }
+
+ public override void Add(JSONNode aItem)
+ {
+ var tmp = new JSONArray();
+ tmp.Add(aItem);
+ Set(tmp);
+ }
+
+ public override void Add(string aKey, JSONNode aItem)
+ {
+ var tmp = new JSONObject();
+ tmp.Add(aKey, aItem);
+ Set(tmp);
+ }
+
+ public static bool operator ==(JSONLazyCreator a, object b)
+ {
+ if (b == null)
+ return true;
+ return System.Object.ReferenceEquals(a, b);
+ }
+
+ public static bool operator !=(JSONLazyCreator a, object b)
+ {
+ return !(a == b);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return true;
+ return System.Object.ReferenceEquals(this, obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return 0;
+ }
+
+ public override int AsInt
+ {
+ get
+ {
+ JSONNumber tmp = new JSONNumber(0);
+ Set(tmp);
+ return 0;
+ }
+ set
+ {
+ JSONNumber tmp = new JSONNumber(value);
+ Set(tmp);
+ }
+ }
+
+ public override float AsFloat
+ {
+ get
+ {
+ JSONNumber tmp = new JSONNumber(0.0f);
+ Set(tmp);
+ return 0.0f;
+ }
+ set
+ {
+ JSONNumber tmp = new JSONNumber(value);
+ Set(tmp);
+ }
+ }
+
+ public override double AsDouble
+ {
+ get
+ {
+ JSONNumber tmp = new JSONNumber(0.0);
+ Set(tmp);
+ return 0.0;
+ }
+ set
+ {
+ JSONNumber tmp = new JSONNumber(value);
+ Set(tmp);
+ }
+ }
+
+ public override bool AsBool
+ {
+ get
+ {
+ JSONBool tmp = new JSONBool(false);
+ Set(tmp);
+ return false;
+ }
+ set
+ {
+ JSONBool tmp = new JSONBool(value);
+ Set(tmp);
+ }
+ }
+
+ public override JSONArray AsArray
+ {
+ get
+ {
+ JSONArray tmp = new JSONArray();
+ Set(tmp);
+ return tmp;
+ }
+ }
+
+ public override JSONObject AsObject
+ {
+ get
+ {
+ JSONObject tmp = new JSONObject();
+ Set(tmp);
+ return tmp;
+ }
+ }
+ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
+ {
+ aSB.Append("null");
+ }
+ }
+ // End of JSONLazyCreator
+
+ public static class JSON
+ {
+ public static JSONNode Parse(string aJSON)
+ {
+ return JSONNode.Parse(aJSON);
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/SimpleJSON.cs.meta b/Assets/Plugins/UnityJSON/SimpleJSON.cs.meta
new file mode 100644
index 0000000..ee587a3
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/SimpleJSON.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ddc8cb1d4c6f34c00a5593a530efb360
+timeCreated: 1501101606
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/UnityJSON/Util.cs b/Assets/Plugins/UnityJSON/Util.cs
new file mode 100644
index 0000000..30df74e
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Util.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace UnityJSON
+{
+ internal static class Util
+ {
+ internal static T GetAttribute (MemberInfo info) where T : Attribute
+ {
+ object[] attributes = info.GetCustomAttributes (typeof(T), true);
+ return (attributes == null || attributes.Length == 0) ? null : attributes [0] as T;
+ }
+
+ internal static Type GetMemberType (MemberInfo memberInfo)
+ {
+ return memberInfo is FieldInfo ?
+ (memberInfo as FieldInfo).FieldType : (memberInfo as PropertyInfo).PropertyType;
+ }
+
+ internal static object GetMemberValue (MemberInfo memberInfo, object obj)
+ {
+ if (memberInfo is FieldInfo) {
+ return (memberInfo as FieldInfo).GetValue (obj);
+ } else {
+ return (memberInfo as PropertyInfo).GetValue (obj, null);
+ }
+ }
+
+ internal static void SetMemberValue (MemberInfo memberInfo, object obj, object value)
+ {
+ if (memberInfo is FieldInfo) {
+ (memberInfo as FieldInfo).SetValue (obj, value);
+ } else {
+ (memberInfo as PropertyInfo).SetValue (obj, value, null);
+ }
+ }
+
+ internal static bool IsJSONExtrasMember (MemberInfo memberInfo, out JSONExtrasAttribute attribute)
+ {
+ Type type = GetMemberType (memberInfo);
+ if (type != typeof(System.Collections.Generic.Dictionary)) {
+ attribute = null;
+ return false;
+ }
+
+ attribute = GetAttribute (memberInfo);
+ return attribute != null;
+ }
+
+ internal static bool IsCustomType (Type type)
+ {
+ return !type.IsEnum && !type.IsPrimitive && (type.IsValueType
+ || (!typeof(IEnumerable).IsAssignableFrom (type)
+ && Nullable.GetUnderlyingType (type) == null
+ && type != typeof(object)));
+ }
+
+ internal static bool IsDictionary (Type type)
+ {
+ return typeof(IDictionary).IsAssignableFrom (type) ||
+ (type.IsGenericType && type.GetGenericTypeDefinition () == typeof(IDictionary<,>));
+ }
+ }
+}
diff --git a/Assets/Plugins/UnityJSON/Util.cs.meta b/Assets/Plugins/UnityJSON/Util.cs.meta
new file mode 100644
index 0000000..bbcad57
--- /dev/null
+++ b/Assets/Plugins/UnityJSON/Util.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a9d540499fd534f9585090cd5623db73
+timeCreated: 1505401304
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..93e08cc
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 adragonite
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/ProjectSettings/AudioManager.asset b/ProjectSettings/AudioManager.asset
new file mode 100644
index 0000000..825ca08
Binary files /dev/null and b/ProjectSettings/AudioManager.asset differ
diff --git a/ProjectSettings/ClusterInputManager.asset b/ProjectSettings/ClusterInputManager.asset
new file mode 100644
index 0000000..2b2644d
Binary files /dev/null and b/ProjectSettings/ClusterInputManager.asset differ
diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset
new file mode 100644
index 0000000..0f724e1
Binary files /dev/null and b/ProjectSettings/DynamicsManager.asset differ
diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset
new file mode 100644
index 0000000..d767445
Binary files /dev/null and b/ProjectSettings/EditorBuildSettings.asset differ
diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset
new file mode 100644
index 0000000..7456bea
Binary files /dev/null and b/ProjectSettings/EditorSettings.asset differ
diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset
new file mode 100644
index 0000000..6abd3c0
Binary files /dev/null and b/ProjectSettings/GraphicsSettings.asset differ
diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset
new file mode 100644
index 0000000..5342fb7
Binary files /dev/null and b/ProjectSettings/InputManager.asset differ
diff --git a/ProjectSettings/NavMeshAreas.asset b/ProjectSettings/NavMeshAreas.asset
new file mode 100644
index 0000000..a92aa3d
Binary files /dev/null and b/ProjectSettings/NavMeshAreas.asset differ
diff --git a/ProjectSettings/NetworkManager.asset b/ProjectSettings/NetworkManager.asset
new file mode 100644
index 0000000..eef089e
Binary files /dev/null and b/ProjectSettings/NetworkManager.asset differ
diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset
new file mode 100644
index 0000000..4bb251e
Binary files /dev/null and b/ProjectSettings/Physics2DSettings.asset differ
diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset
new file mode 100644
index 0000000..c33f4c5
Binary files /dev/null and b/ProjectSettings/ProjectSettings.asset differ
diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt
new file mode 100644
index 0000000..6e4d03d
--- /dev/null
+++ b/ProjectSettings/ProjectVersion.txt
@@ -0,0 +1 @@
+m_EditorVersion: 5.6.1f1
diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset
new file mode 100644
index 0000000..50e78ad
Binary files /dev/null and b/ProjectSettings/QualitySettings.asset differ
diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset
new file mode 100644
index 0000000..2c3af94
Binary files /dev/null and b/ProjectSettings/TagManager.asset differ
diff --git a/ProjectSettings/TimeManager.asset b/ProjectSettings/TimeManager.asset
new file mode 100644
index 0000000..0838e4e
Binary files /dev/null and b/ProjectSettings/TimeManager.asset differ
diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset
new file mode 100644
index 0000000..08a6236
Binary files /dev/null and b/ProjectSettings/UnityConnectSettings.asset differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5b082c6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,598 @@
+# UnityJSON
+
+> Customizable JSON Serialization / Deserialization for C# in Unity
+
+**Table Of Contents:**
+
+* [Features](#features)
+* [Installation](#installation)
+* [Serialization](#serialization)
+ - [Enums](#enums)
+ - [Serialization Lifecycle](#serialization-lifecycle)
+ - [Custom Serialization with Serializer](#custom-serialization-with-serializer)
+ - [Custom Serialization with ISerializable](#custom-serialization-with-iserializable)
+* [Deserialization](#deserialization)
+ - [Deserialized Types](#deserialized-types)
+ - [Deserialization of Extra Nodes](#deserialization-of-extra-nodes)
+ - [Deserialization with Inheritance](#deserialization-with-inheritance)
+ - [Deserialization Lifecycle](#deserialization-lifecycle)
+ - [Custom Deserialization with Deserializer](#custom-deserialization-with-deserializer)
+ - [Custom Deserialization with IDeserializable](#custom-deserialization-with-ideserializable)
+
+## Features
+
+UnityJSON provides direct JSON serialization / deserialization between
+C# objects and JSON strings. Main features of UnityJSON are:
+
+- Serializes all primitive types, enums, structs and classes into JSON
+string directly.
+- Deserializes all primitive types, enums, most of the structs and classes
+from JSON string directly.
+- Supports inheritence during deserialization.
+- Supports formatting for enums.
+- Supports formatting of serialized / deserialized fields and
+properties.
+- Supports Unity types (Vectors, Quaternions, Color, Rect, Bounds).
+- Provides further customization of serialization / deserialization process.
+
+UnityJSON works with reflection using C# attributes. The following is a very
+simple example using UnityJSON:
+
+```cs
+using UnityJSON;
+
+public class ParentClass
+{
+ // Supports structs.
+ public struct NestedStruct
+ {
+ // Supports Unity Vectors
+ public Vector2 vectorField;
+ }
+
+ // Supports properties.
+ public NestedStruct structProperty { get; set; }
+
+ // Supports deserialization to interfaces.
+ public IList listField;
+}
+
+// Deserialization
+var parentObject = JSON.Deserialize(
+ "{\"structProperty\": {\"vectorField\": " +
+ "{\"x\":1, \"y\": 2}}, \"listField\":[true]}");
+
+// Serialization
+parentObject.ToJSONString();
+```
+
+## Installation
+
+Simply use the `unityjson.unitypackage` to add it to your project.
+
+## Serialization
+
+You can serialize objects with `object.ToJSONString()` or `JSON.Serialize(object)`
+methods. By default, only public instance fields and properties of an object are
+serialized, however, you can customize the serialized properties with the use
+of `JSONNode` and `JSONObject` attributes.
+
+```cs
+// Include statics in the serialization / deserialization.
+[JSONObject(ObjectOptions.IncludeStatic)]
+public class AClass
+{
+ // Serialized because of ObjectOptions.IncludeStatic.
+ public static int staticIntField;
+
+ // Serialize although it is a private field.
+ [JSONNode]
+ private static string staticStringField;
+
+ // Don't serialize although it is a public property.
+ [JSONNode(NodeOptions.DontSerialize)]
+ public IDictionary dictionaryField;
+
+ // Serialize this field even if it is null. When serializing
+ // use the key "customField" instead of "stringField".
+ [JSONNode(NodeOptions.SerializeNull, key = "customField")]
+ private string stringField;
+}
+```
+
+`JSONNodeAttribute`s are the main attributes for fields and properties, and define
+their serialization / deserialization configuration. The attribute contains options
+in the form of `NodeOptions` enum and an optional custom key for the field or property.
+The node options only affect the field or property they are bound to with some minor
+exceptions when using enumerable types. For serialization, the following node options
+might be useful:
+
+- DontSerialize: Ignores the field / property during serialization. Can be used with
+public fields / properties that should not be serialized.
+- SerializeNull: By default if a value is null, it is simply ignored and not serialized
+(except for enumerables other than dictionaries such as lists or arrays). This option
+makes sure that the field / property is serialized anyway. When bound to a dictionary
+(IDictionary, IDictionary<,>, ...), this option also affects the values of the dictionary.
+
+`JSONObjectAttribute`s offer general control over the serialization / deserialization
+process. They can be added to classes and structs to inform the serializer where to look
+at. It uses the `ObjectOptions` enum which has the following serialization options:
+
+- IgnoreProperties: Ignores all properties from serialization / deserialization.
+- IncludeStatic: Includes static fields and properties in serialization / deserialization.
+
+### Enums
+
+Enums are by default serialized directly with their member names. Their serialization
+can, however, be customized with the use of `JSONEnumAttribute`. The attribute allows the
+following formating options:
+
+- useIntegers: The enums are serialized / deserialized according to their numeric values.
+- format: Optional formatting to be applied given in the form of `JSONEnumMemberFormating`.
+It supports lowercase, uppercase or captialize (only the first letter is captialized).
+- prefix: Adds an optional prefix to the formatted member name.
+- suffix: Adds an optional suffix to the formatted member name.
+
+```cs
+[JSONEnum(format = JSONEnumMemberFormating.Lowercased, suffix = "Position")]
+public enum Positions
+{
+ Forward
+}
+
+JSON.Serialize(Positions.Forward) // forwardPosition
+```
+
+### Serialization Lifecycle
+
+You can listen to the serialization lifecycle of an object by implementing the
+`ISerializationListener` interface.
+
+```cs
+public class AClass : ISerializationListener
+{
+ void ISerializationListener.OnSerializationWillBegin(Serializer serializer)
+ {
+ Debug.Log ("Serialization started.");
+ }
+
+ void ISerializationListener.OnSerializationSucceeded(Serializer serializer)
+ {
+ Debug.Log ("Serialization ended successfully.");
+ }
+
+ void ISerializationListener.OnSerializationFailed(Serializer serializer)
+ {
+ Debug.Log ("Serialization failed.");
+ }
+}
+```
+
+The `OnSerializationWillBegin` call is always followed by either the success or
+fail call. The fail method is called just before throwing an exception.
+
+### Custom Serialization with Serializer
+
+Serializer is the actual component that performs the serialization. The
+basic serializer can be accessed with `Serializer.Simple`. When no specific
+serializer is given, the default serializer is used (`Serializer.Default`). The
+default serializer is the simple serializer unless set otherwise. You can
+create your own serializer by simply subclassing `Serializer`. You should then
+override the `Serializer.TrySerialize` method to perform your application
+specific serialization.
+
+```cs
+public class SpecialSerializer : Serializer
+{
+ protected override bool TrySerialize (
+ object obj,
+ NodeOptions options,
+ out string serialized)
+ {
+ // obj is always guaranteed to be non-null.
+ if (obj.GetType() == typeof(MySpecialClass)) {
+ serialized = MySpecialSerializeFunction();
+ return true;
+ } else {
+ // Returning false will simply run the regular
+ // serialization.
+ return false;
+ }
+ }
+}
+
+var obj = new MySpecialClass();
+obj.ToJSONString(new SpecialSerializer());
+```
+
+You can then pass this new serializer as an argument in the `object.ToJSONString`
+method or set it as the default serializer to be used automatically. The classes that
+are serialized with the `Serializer.TrySerialize` method do not receive serialization
+lifecycle calls from `ISerializationListener`.
+
+### Custom Serialization with ISerializable
+
+Another way to provide custom serialization is by implementing the interface
+`ISerializable`. It is important to notice that `Serializer.TrySerialize` is called
+first and this interface will be ignored if that method returns true.
+
+```cs
+public class AClass : ISerializable
+{
+ string ISerializable.Serialize(Serializer serializer)
+ {
+ return "{" + serializer.SerializeEnum (MyEnum.Value) + "}";
+ }
+}
+```
+
+The classes that are serialized with the `ISerializable.Serialize` method do not receive
+serialization lifecycle calls from `ISerializationListener`.
+
+## Deserialization
+
+You can perform deserialization by calling `JSON.Deserialize\(jsonString)` method.
+This will instantiate a new object of that type and fill it with the data from the
+JSON string. If you wish to use a previously created object, you can also use one of the
+`JSON.DeserializeOn(obj, jsonString)` or `obj.FeedJSON(jsonString)` methods. This object
+can either be a struct or a class.
+
+Deserialization can be more cumbersome then it's counterpart as the serialization of an
+object is unique whereas the deserialization of a JSON string can produce different
+results. The basic JSON types allow the following deserialization approaches:
+
+- JSON string: System.String (string)
+- JSON bool: System.Boolean (bool)
+- JSON number: System.Int32 (int), System.UInt32 (uint), System.Byte (byte),
+System.Single (float), System.Double (double)
+- JSON array: System.Array, IList, IList\<\>, List\<\>
+- JSON dictionary: IDictionary, IDictionary\<,\>, Dictionary\<,\>, custom classes and structs
+
+UnityJSON aims to support a lot of the main system classes such as lists and dictionaries.
+However, not everything is supported directly by framework, for instance LinkedLists are
+not supported for deserialization at the moment.
+
+The framework decides the type to deserialize into from the type of the field or property.
+This is important as the deserializer needs to instantiate an object from the given type
+only. If an interface such as `IList` is used, then a default instantiated object type is
+defined, `List<>` is used for instance for `IList`.
+
+`JSONNode` and `JSONObject` attributes are also used for deserialization and provide
+more options.
+
+```cs
+// If an unknown key is received during deserialization, simply
+// ignore it instead of throwing an exception.
+[JSONObject(ObjectOptions.IgnoreUnknownKey)]
+public class AClass
+{
+ // Automatically ignored at deserialization as the property
+ // does not have a setter.
+ public float propertyField { get; }
+
+ // Deserialize although it is a private field.
+ [JSONNode]
+ private string stringField;
+
+ // Don't deserialize although it is a public property.
+ [JSONNode(NodeOptions.DontDeserialize)]
+ public IDictionary dictionaryField;
+
+ // Don't throw an exception even if the deserialized object
+ // doesn't match the type (Vector2 expects "x" and "y" keys).
+ [JSONNode(NodeOptions.IgnoreTypeMismatch)]
+ public Vector2 vectorField;
+
+ // Don't throw an exception even if the deserializer cannot
+ // instantiate an object for the type. This can for example
+ // happen for classes without a default constructor.
+ [JSONNode(NodeOptions.IgnoreUnknownType)]
+ public ClassWithConstructor classField;
+
+ // Even if the JSON object has a "customField" key, don't
+ // assign it if it is null, simply ignore it.
+ [JSONNode(NodeOptions.DontAssignNull, key = "customField")]
+ private string stringField2;
+}
+```
+
+Deserialization process tends to throw a lot of `DeserializationException`s exceptions in
+case of any problems. By default, the exception is thrown in the following scenarios:
+
+- The JSON string is not applicable to the target type. For instance the target type is
+a string and the node contains a boolean value. This is called a type mismatch error. You
+can ignore it with the `NodeOptions.IgoreTypeMismatch` option.
+- The target type cannot be instantiated or is not supported. This is called an unknown
+type error. You can ignore it with the `NodeOptions.IgnoreUnknownType` option.
+- The JSON node cannot contain unknown keys that cannot be mapped to the fields and properties
+of the class / struct. In such a scenario an exception is thrown, this is called an
+unknown key error and can be ignored with `ObjectOptions.IgnoreUnknownKey` option given
+in a `JSONObjectAttribute` to the class or struct. Another option to ignore this error is
+by using an extras dictionary (see [Deserialization of Extra Nodes](#deserialization-of-extra-nodes)).
+
+`NodeOptions` also offer the following other options for the deserialization process:
+
+- DontDeserialize: Ignore the field / property from the deserialization process. Similar
+to `NodeOptions.DontSerialize` for serialization.
+- DontAssignNull: By default if a key exists in the node its value is assigned to the
+associated field or property automatically even if it is null. This option makes sure
+that the null assignments are simply ignored by the deserializer. This can be particularly
+useful to use with `NodeOptions.IgnoreTypeMismatch` because when the type mismatch errors
+are ignored, in case of a type mismatch the deserializer always returns null. For
+primitive types, null is mapped to the intricate default value (0 for int, false for bool).
+By using this option, you can prevent the deserializer from assigning the default values
+upon type mismatch errors.
+- ReplaceDeserialized: The deserializer tries to reuse the previously created objects
+when deserializing. If a field is of type T and it is instantiated, when the deserializer
+recevies values for this object of type T, it simply assigns them directly to the already
+existing object. This option forces the deserializer to instantiate a new object instead
+completely build from the data recevied. This option can only be used for custom classes
+that do not implement IEnumerable interface. An example can be seen below:
+
+```cs
+public class A
+{
+ public int intField;
+ public float floatField;
+}
+
+public struct B
+{
+ public A a1 = new A();
+
+ [JSONNode(NodeOptions.ReplaceDeserialized)]
+ public A a2 = new A();
+}
+
+B b = new B();
+
+// Without ReplaceDeserialized
+b.a1.floatField = 2;
+B deserializedB = JSON.Deserialize("{\"a1:{\"intField\":1}}");
+deserializedB.a1.intField // 1 (from the deserialization)
+deserializedB.a1.floatField // 2 (from the previous assignment, object reused)
+
+// With ReplaceDeserialized
+b.a2.floatField = 2;
+B deserializedB2 = JSON.Deserialize("{\"a2:{\"intField\":1}}");
+deserializedB2.a2.intField // 1 (from the deserialization)
+deserializedB2.a2.floatField // 0 (new object of type A is instantiated)
+```
+
+### Deserialized Types
+
+The deserialization is currently defined for the following target types:
+
+- int, uint, byte, bool, float, double
+- Enums (see [Enums](#enums) for fomatting details)
+- T[]: Type T must be supported
+- System.Array: Instantiates object[]
+- List\: Type T must be supported
+- IList\: Instantiates List\
+- IList: Instantiates List\
+- Dictionary\: K must be primitive, enum or string. V must be supported.
+- IDictionary\: Instantiates Dictionary\
+- IDictionary: Instantiates Dictionary\
+- Custom classes or structs: Must have a default constructor without arguments.
+
+The type `object` is also supported and the deserialization for this target
+is performed according to JSON node at hand with the following mapping:
+
+- JSON string: string
+- JSON number: double
+- JSON bool: bool
+- JSON array: object[]
+- JSON dictionary: Dictionary\
+
+You may, however, want to restrict the supported types and/or support custom
+types too. You can use the `RestrictTypeAttribute` for that. This attribute takes
+`ObjectTypes` enum value and an optional custom types array. The `ObjectTypes`
+enum define which types to look for, the default value is `ObjectTypes.JSON`
+and supports all types except custom. If the custom types are supported (by
+either using `ObjectTypes.All` or `ObjectTypes.Custom`) then an additional
+array of custom types can be given to try deserializing the object into them.
+Custom types are classes or structs cannot be enumerable and nullable. The order
+of the custom types are important as they are tried one by one. If no type can
+be deserialized into, then a generic dictionary is created (unless the dictionary
+type is not supported, in which case an exception is thrown).
+
+```cs
+class A
+{
+ public int intField;
+}
+
+class B
+{
+ public float floatField;
+}
+
+class C
+{
+ [RestrictType(ObjectTypes.Custom, customTypes = new Type[] {A, B})]
+ public object field;
+}
+
+var c = JSON.Deserialize("{\"field\":{\"floatField\":5}}");
+c.field // object of type B with floatField 5
+```
+
+`RestrictTypeAttribute` can also be used with IList, IList\, List\,
+object[], IDictionary, IDictionary\, Dictionary\.
+
+### Deserialization of Extra Nodes
+
+Sometimes you may receive more key / value pairs than what your class and struct supports.
+By default, the deserializer will throw an exception in this case unless
+`ObjectOptions.IgnoreUnknownKey` is used. You can, however, also decide to parse these
+extras into your class / struct. You can do that by adding a field or property with
+`JSONExtrasAttribute`. The type of the field or the object must be Dictionary\.
+The attribute can also have optional `NodeOptions`. A field or a property with this
+attribute is never serialized or deserialized even if it is public.
+
+```cs
+class A
+{
+ [JSONExtras]
+ public Dictionary extras;
+}
+
+A a = JSON.Deserialize("{\"key\":5}");
+a.extras["key"] // 5
+```
+
+You can also use `RestrictTypeAttribute` to restrict the supported types or use custom
+types. The extras are also used for the serialization and are serialized on the same level
+as the object.
+
+### Deserialization with Inheritance
+
+You may want to provide deserialization to interface or abstract class targets. One option
+would be to use a custom deserializer
+(see [Custom Deserialization: Deserializer](#custom-deserialization-with-deserializer)), however
+in most cases you can also simply do that by using `ConditionalInstantiation` and
+`DefaultInstantiation` attributes. These can redirect the instantiated types for an
+interface or a class. `ConditionalInstantiationAttribute` checks for a key value pair in
+the received JSON node and instantiates the referenced type if there is match. If no
+condition is met, then the referenced type from `DefaultInstantiationAttribute` is
+instantiated. If no such attribute exists, then the default framework deserialization
+is performed.
+
+```cs
+[ConditionalInstantiation(typeof(A), "type", 0)]
+[ConditionalInstantiation(typeof(B), "type", 1)]
+[DefaultInstantiation(typeof(C))]
+interface I
+{
+}
+
+class A : I
+{
+ public int type;
+}
+
+class B : I
+{
+ public int type;
+}
+
+[JSONObject(ObjectOptions.IgnoreUnknownKey)]
+class C : I
+{
+}
+
+I obj = JSON.Deserialize("{\"type\":1}"); // obj is of type B.
+```
+
+### Deserialization Lifecycle
+
+You can listen to the deserialization lifecycle of an object by implementing the
+`IDeserializationListener` interface.
+
+```cs
+public class AClass : IDeserializationListener
+{
+ void IDeserializationListener.OnDeserializationWillBegin(Deserializer deserializer)
+ {
+ Debug.Log ("Deserialization started.");
+ }
+
+ void IDeserializationListener.OnDeserializationSucceeded(Deserializer deserializer)
+ {
+ Debug.Log ("Deserialization ended successfully.");
+ }
+
+ void IDeserializationListener.OnDeserializationFailed(Deserializer deserializer)
+ {
+ Debug.Log ("Deserialization failed.");
+ }
+}
+```
+
+The `OnDeserializationWillBegin` call is always followed by either the success or
+fail call. The fail method is called just before throwing an exception.
+
+## Custom Deserialization with Deserializer
+
+Deserializer is the actual component that performs the deserialization. The
+basic deserializer can be accessed with `Deserializer.Simple`. When no specific
+deserializer is given, the default deserializer is used (`Deserializer.Default`).
+The default deserializer is the simple deserializer unless set otherwise. You can
+create your own deserializer by simply subclassing `Deserializer`. You should then
+override the `Deserializer.TryInstantiate` and `Deserializer.TryDeserializeOn` methods
+to perform your application specific deserialization. These two methods are
+independent of each other and represent the two steps of deserialization:
+instantiation of the object and feeding the JSON string inside. You can decide to
+override only one method too.
+
+```cs
+public class SpecialDeserializer : Deserializer
+{
+ protected override bool TryInstantiate (
+ JSONNode node,
+ Type type,
+ NodeOptions options,
+ out object instantiatedObject)
+ {
+ if (type == typeof(MySpecialClass)) {
+ // Custom deserializers can be used to instantiate classes
+ // with constructors.
+ instantiatedObject = new MySpecialClass(node["key"]);
+ return true;
+ } else {
+ // Returning false will simply run the regular
+ // instantiation process.
+ return false;
+ }
+ }
+
+ protected override bool TryDeserialize (
+ object obj,
+ JSONNode node,
+ NodeOptions options)
+ {
+ // obj is always guaranteed to be non-null.
+ if (obj.GetType() == typeof(MySpecialClass)) {
+ MySpecialDeserializeFunction(obj, node);
+ return true;
+ } else {
+ // Returning false will simply run the regular
+ // deserialization process.
+ return false;
+ }
+ }
+}
+
+var deserializer = new SpecialDeserializer();
+var obj = JSON.Deserialize(jsonString, deserializer);
+```
+
+When the `Deserializer.Deserialize` method is called, it first tries to
+instantiate the object with the `Deserializer.TryInstantiate` method, if
+that fails, then the regular type based instantiation is performed. When
+the object is instantiated, the `Deserializer.DeserializeOn` method is called
+on the object. This first tries the custom `Deserializer.TryDeserialize`
+method and then performs the regular framework deserialization if that fails.
+
+The classes that are deserialized with the `Deserializer.TryDeserialize` method
+do not receive deserialization lifecycle calls from `IDeserializationListener`.
+
+## Custom Deserialization with IDeserializable
+
+Another way to provide custom deserialization is by implementing the interface
+`IDeserializable`. It is important to notice that `Deserializer.TryDeserialize` is called
+first and this interface will be ignored if that method returns true. In addition,
+you still need to make sure that your class can be instantiated.
+
+```cs
+public class AClass : IDeserializable
+{
+ void IDeserializable.Deserialize(JSONNode node, Deserializer deserializer)
+ {
+ listField.AddRange (deserializer.DeserializeToList(node["list"]));
+ }
+}
+```
+
+The classes that are deserialized with the `IDeserializable.Deserialize` method do
+not receive deserialization lifecycle calls from `IDeserializationListener`.
diff --git a/unityjson.unitypackage b/unityjson.unitypackage
new file mode 100644
index 0000000..2ae240b
Binary files /dev/null and b/unityjson.unitypackage differ