using System; using System.Collections.Generic; namespace UnityEngine.Graphing { public static class SerializationHelper { [Serializable] public struct TypeSerializationInfo { [SerializeField] public string fullName; [SerializeField] public string assemblyName; public bool IsValid() { return !string.IsNullOrEmpty(fullName) && !string.IsNullOrEmpty(assemblyName); } public string SearchString() { if (!IsValid()) return string.Empty; return string.Format("{0}, {1}", fullName, assemblyName); } public string SearchStringTestable() { if (!IsValid()) return string.Empty; return string.Format("{0}, {1}-testable", fullName, assemblyName); } } [Serializable] public struct JSONSerializedElement { [SerializeField] public TypeSerializationInfo typeInfo; [SerializeField] public string JSONnodeData; } public static JSONSerializedElement nullElement { get { return new JSONSerializedElement(); } } public static TypeSerializationInfo GetTypeSerializableAsString(Type type) { return new TypeSerializationInfo { fullName = type.FullName, assemblyName = type.Assembly.GetName().Name }; } private static Type GetTypeFromSerializedString(TypeSerializationInfo typeInfo) { if (!typeInfo.IsValid()) return null; var res = Type.GetType(typeInfo.SearchString()); // if we are using a 'testable' dll. if (res == null) res = Type.GetType(typeInfo.SearchStringTestable()); return res; } public static JSONSerializedElement Serialize(T item) { if (item == null) throw new ArgumentNullException("item", "Can not serialize null element"); var typeInfo = GetTypeSerializableAsString(item.GetType()); var data = JsonUtility.ToJson(item, true); if (string.IsNullOrEmpty(data)) throw new ArgumentException(string.Format("Can not serialize {0}", item)); ; return new JSONSerializedElement { typeInfo = typeInfo, JSONnodeData = data }; } private static TypeSerializationInfo DoTypeRemap(TypeSerializationInfo info, Dictionary remapper) { TypeSerializationInfo foundInfo; if (remapper.TryGetValue(info, out foundInfo)) return foundInfo; return info; } public static T Deserialize(JSONSerializedElement item, Dictionary remapper, params object[] constructorArgs) where T : class { if (!item.typeInfo.IsValid() || string.IsNullOrEmpty(item.JSONnodeData)) throw new ArgumentException(string.Format("Can not deserialize {0}, it is invalid", item)); TypeSerializationInfo info = item.typeInfo; if (remapper != null) info = DoTypeRemap(info, remapper); info.assemblyName = "Assembly-CSharp-Editor"; var type = GetTypeFromSerializedString(info); if (type == null) throw new ArgumentException(string.Format("Can not deserialize ({0}, {1}), type is invalid", info.assemblyName, info.fullName)); T instance; try { instance = Activator.CreateInstance(type, constructorArgs) as T; } catch (Exception e) { throw new Exception(string.Format("Could not construct instance of: {0}", type), e); } if (instance != null) { JsonUtility.FromJsonOverwrite(item.JSONnodeData, instance); return instance; } return null; } public static List Serialize(IEnumerable list) { var result = new List(); if (list == null) return result; foreach (var element in list) { try { result.Add(Serialize(element)); } catch (Exception e) { Debug.LogException(e); } } return result; } public static List Deserialize(IEnumerable list, Dictionary remapper, params object[] constructorArgs) where T : class { var result = new List(); if (list == null) return result; foreach (var element in list) { try { result.Add(Deserialize(element, remapper)); } catch (Exception e) { Debug.LogException(e); Debug.LogError(element.JSONnodeData); } } return result; } } }