Example #1
0
    private object ReadObject()
    {
        if (_reader.NodeType != JsonNodeType.Object)
        {
            throw new SerializationException("Failed to deserialize due to malformed json.");
        }

        _reader.Read();
        if (_reader.NodeType != JsonNodeType.String || _reader.Name != ID_TYPE)
        {
            throw new SerializationException("Failed to deserialize due to malformed json: objects must contain a @type property.");
        }

        var tp = Type.GetType(_reader.Value as string);

        if (tp == null)
        {
            tp = TypeUtil.FindType(_reader.Value as string, true);
        }
        if (tp == null)
        {
            throw new SerializationException("Failed to deserialize due to malformed json: objects must contain a @type property.");
        }

        object result;
        ISerializationSurrogate surrogate;
        ISurrogateSelector      selector;

        if (this.SurrogateSelector != null && (surrogate = this.SurrogateSelector.GetSurrogate(tp, this.Context, out selector)) != null)
        {
            var si = this.ReadAsSerializationInfo(tp);
            try
            {
                var obj = FormatterServices.GetUninitializedObject(tp);

                if (tp.FullName == "Serialization.PersistentObject")
                {
                    // TODO: Remove this hack. Use tokens instead of trying to directly serialize PersistentObject--the descedant of MonoBehavior

                    obj = PersistenceController.GetPrecreatedPersistentObject(new PersistentUid(si.GetString("uid")));

                    if (obj == null)
                    {
                        string linkedPrefabUid = si.GetString("linkedPrefabUid");
                        if (linkedPrefabUid != "")
                        {
                            PersistentObject prefab = PersistenceController.GetRegisteredPrefab(linkedPrefabUid);
                            obj = GameObject.Instantiate(prefab);
                        }
                    }
                }

                result = surrogate.SetObjectData(obj, si, this.Context, selector);
            }
            catch (System.Exception ex)
            {
                throw new SerializationException("Failed to deserialize.", ex);
            }
        }
        else if (typeof(ISerializable).IsAssignableFrom(tp))
        {
            var si          = this.ReadAsSerializationInfo(tp);
            var constructor = GetSerializationConstructor(tp);
            if (constructor == null)
            {
                throw new SerializationException("Failed to deserialize due to ISerializable type '" + tp.FullName + "' not implementing the appropriate constructor.");
            }
            try
            {
                result = constructor.Invoke(new object[] { si, this.Context });
            }
            catch (System.Exception ex)
            {
                throw new SerializationException("Failed to deserialize.", ex);
            }
        }
        else
        {
            var members = FormatterServices.GetSerializableMembers(tp, Context);
            var data    = new object[members.Length];

            while (_reader.Read())
            {
                var weqw = _reader.NodeType;

                switch (_reader.NodeType)
                {
                case JsonNodeType.None:
                case JsonNodeType.EndArray:
                    throw new SerializationException("Failed to deserialize due to malformed json.");

                case JsonNodeType.Object:
                {
                    var nm = _reader.Name;
                    int i  = GetIndexOfMemberName(members, nm);
                    if (i < 0)
                    {
                        this.ReadPastObject();
                    }
                    else
                    {
                        data[i] = this.ReadObject();
                    }
                }
                break;

                case JsonNodeType.Array:
                {
                    var nm = _reader.Name;
                    int i  = GetIndexOfMemberName(members, nm);
                    if (i < 0)
                    {
                        this.ReadPastArray();
                    }
                    else
                    {
                        _reader.Read();
                        if (_reader.NodeType != JsonNodeType.String)
                        {
                            throw new SerializationException("Failed to deserialize due to malformed json: array must begin with a @type string. (" + nm + ")");
                        }

                        System.Type arrayType = null;
                        try
                        {
                            var stp = _reader.Value as string;
                            //bool isArray = (stp != null && stp.EndsWith("[]"));
                            //if (isArray) stp = stp.Substring(0, stp.Length - 2);
                            //arrayType = Type.GetType(stp);
                            //if (arrayType == null) arrayType = TypeUtil.FindType(stp, true);
                            //if (arrayType != null && isArray) arrayType = arrayType.MakeArrayType();
                            if (string.IsNullOrEmpty(stp))
                            {
                                arrayType = null;
                            }
                            else if (stp.EndsWith("[]"))
                            {
                                stp       = stp.Substring(0, stp.Length - 2);
                                arrayType = Type.GetType(stp);
                                if (arrayType == null)
                                {
                                    arrayType = TypeUtil.FindType(stp, true);
                                }
                                if (arrayType != null)
                                {
                                    arrayType = arrayType.MakeArrayType();
                                }
                            }
                            else if (stp.EndsWith("<>"))
                            {
                                stp       = stp.Substring(0, stp.Length - 2);
                                arrayType = Type.GetType(stp);
                                if (arrayType == null)
                                {
                                    arrayType = TypeUtil.FindType(stp, true);
                                }
                                if (arrayType != null)
                                {
                                    arrayType = typeof(List <>).MakeGenericType(arrayType);
                                }
                            }
                        }
                        catch (System.Exception)
                        {
                            throw new SerializationException("Failed to deserialize due to malformed json: array must begin with a @type string. (" + nm + ")");
                        }
                        if (arrayType == null)
                        {
                            throw new SerializationException("Failed to deserialize due to malformed json: array must begin with a @type string. (" + nm + ")");
                        }

                        var innerType = arrayType.IsArray ? arrayType.GetElementType() : arrayType.GetGenericArguments()[0];
                        data[i] = this.ReadArray(nm, innerType, !arrayType.IsArray);
                    }
                }
                break;

                case JsonNodeType.String:
                case JsonNodeType.Number:
                case JsonNodeType.Boolean:
                case JsonNodeType.Null:
                {
                    int i = GetIndexOfMemberName(members, _reader.Name);
                    if (i < 0)
                    {
                        this.ReadPastObject();
                    }
                    else
                    {
                        data[i] = ConvertJsonValueToType(_reader.Value, (members[i] as System.Reflection.FieldInfo).FieldType);
                    }
                }
                break;

                case JsonNodeType.EndObject:
                    goto Result;
                }
            }

Result:
            result = FormatterServices.GetUninitializedObject(tp);
            FormatterServices.PopulateObjectMembers(result, members, data);
        }

        if (result is IDeserializationCallback)
        {
            (result as IDeserializationCallback).OnDeserialization(this);
        }
        return(result);
    }