Ejemplo n.º 1
0
 bool IJsonInterceptor.OnDeserializing(object data, JsonItem item)
 {
     if (data is T)
     {
         return(OnDeserializing((T)data, item));
     }
     return(false);
 }
Ejemplo n.º 2
0
        void ConvertProperty(object o, JsonMemberSetter pi, JsonItem ji)
        {
            var pc = pi.Converter ?? pi.TypeInfo.Converter;
            var rt = pc.GetReversiveType(ji);
            var xv = ji._Value;

            if (xv != null && rt != null && pi.Member.MemberType.Equals(xv.GetType()) == false)
            {
                var c  = _manager.GetSerializationInfo(rt);
                var jt = Reflection.GetJsonDataType(rt);
                if (jt != JsonDataType.Undefined)
                {
                    xv = c.DeserializeMethod(this, xv, c);
                }
                else if (xv is JsonDict)
                {
                    xv = CreateObject((JsonDict)xv, c, pi.Member.Getter(o));
                }
            }
            ji._Value = pc.DeserializationConvert(xv);
        }
Ejemplo n.º 3
0
        // HACK: This is a very long function, individual parts in regions are made inline for better performance
        internal void WriteObject(object obj, SerializationInfo info)
        {
            var def = info ?? _manager.GetSerializationInfo(obj.GetType());

            #region Detect Circular Reference
            if (def.Reflection.CircularReferencable)
            {
                var ci = 0;
                if (_cirobj == null)
                {
                    _cirobj = new Dictionary <object, int> ();
                }
                if (_cirobj.TryGetValue(obj, out ci) == false)
                {
                    _cirobj.Add(obj, _cirobj.Count + 1);
                }
                else
                {
                    if (_currentDepth > 0 && _useExtensions && _manager.InlineCircularReferences == false)
                    {
                        //_circular = true;
                        OutputText("{\"" + JsonDict.ExtRefIndex + "\":");
                        OutputText(ValueConverter.Int32ToString(ci));
                        OutputChar('}');
                        return;
                    }
                }
            }
            #endregion
            var si = def.Interceptor;
            if (si != null && si.OnSerializing(obj) == false)
            {
                return;
            }

            OutputChar('{');

            _currentDepth++;
            if (_currentDepth > _maxDepth)
            {
                throw new JsonSerializationException("Serializer encountered maximum depth of " + _maxDepth + ". Last object name on stack: " + def.Reflection.AssemblyName);
            }

            var append = false;
            #region Write Type Reference
            if (def.Reflection.IsAbstract || def.Alias != null)
            {
                WritePairFast(JsonDict.ExtType, def.Alias ?? def.Reflection.TypeName);
                append = true;
            }
            else if (_useExtensions && info == null && def.Reflection.IsAnonymous == false ||
                     def.Reflection.Type.Equals(obj.GetType()) == false)
            {
                WritePairFast(JsonDict.ExtType, def.Reflection.TypeName);
                append = true;
            }
            #endregion

            var g = def.Getters;
            var c = g.Length;
            for (int ii = 0; ii < c; ii++)
            {
                var p = g[ii];
                var m = p.Member;
                #region Skip Members Not For Serialization
                if (p.Serializable == TriState.False)
                {
                    continue;
                }
                if (p.Serializable == TriState.Default)
                {
                    if (m.IsStatic && _manager.SerializeStaticMembers == false ||
                        m.IsReadOnly && p.TypeInfo.Reflection.AppendItem == null &&
                        (m.IsProperty && _showReadOnlyProperties == false || m.IsProperty == false && _showReadOnlyFields == false))
                    {
                        continue;
                    }
                }
                #endregion
                var ji = new JsonItem(m.MemberName, m.Getter(obj), true);
                if (si != null && si.OnSerializing(obj, ji) == false)
                {
                    continue;
                }
                var cv = p.Converter ?? p.TypeInfo.Converter;
                if (cv != null)
                {
                    ji._Value = cv.SerializationConvert(ji._Value);
                }
                #region Convert Items
                var ic = p.ItemConverter;
                if (ic == null && p.TypeInfo.TypeParameters != null && p.Member.IsNullable == false)
                {
                    var it = p.TypeInfo.TypeParameters[0];                     // item type
                    ic = it.Converter;
                }
                if (ic != null)
                {
                    var ev = ji._Value as IEnumerable;
                    if (ev != null)
                    {
                        var ol = new List <object> ();
                        foreach (var item in ev)
                        {
                            ol.Add(ic.SerializationConvert(item));
                        }
                        ji._Value = ol;
                    }
                }
                #endregion

                #region Determine Serialized Field Name
                if (p.SpecificName)
                {
                    if (ji._Value == null || p.TypedNames == null || p.TypedNames.TryGetValue(ji._Value.GetType(), out ji._Name) == false)
                    {
                        ji._Name = p.SerializedName;
                    }
                }
                else
                {
                    ji._Name = p.SerializedName;
                }
                #endregion

                #region Skip Null, Default Value or Empty Collection
                if (_manager.SerializeNullValues == false && (ji._Value == null || ji._Value is DBNull))
                {
                    continue;
                }
                if (p.HasNonSerializedValue && Array.IndexOf(p.NonSerializedValues, ji._Value) != -1)
                {
                    // ignore fields with default value
                    continue;
                }
                if (m.IsCollection && _manager.SerializeEmptyCollections == false)
                {
                    var vc = ji._Value as ICollection;
                    if (vc != null && vc.Count == 0)
                    {
                        continue;
                    }
                }
                #endregion
                if (append)
                {
                    OutputChar(',');
                }

                #region Write Name
                if (p.SpecificName)
                {
                    WriteStringFast(ji._Name);
                    OutputChar(':');
                }
                else
                {
                    OutputName(ji._Name);
                }
                #endregion

                #region Write Value
                if (p.SerializeMethod != null && cv == null)
                {
                    var v = ji._Value;
                    if (v == null || v is DBNull)
                    {
                        OutputText("null");
                    }
                    else if (p.TypeInfo.CollectionName != null)
                    {
                        WriteObject(v, p.TypeInfo);
                    }
                    else
                    {
                        p.SerializeMethod(this, v);
                    }
                }
                else
                {
                    WriteValue(ji._Value);
                }
                #endregion

                append = true;
            }
            #region Write Inherited Collection
            if (def.CollectionName != null && def.SerializeMethod != null)
            {
                if (append)
                {
                    OutputChar(',');
                }
                WriteStringFast(def.CollectionName);
                OutputChar(':');
                def.SerializeMethod(this, obj);
                append = true;
            }
            #endregion

            #region Write Extra Values
            if (si != null)
            {
                var ev = si.SerializeExtraValues(obj);
                if (ev != null)
                {
                    foreach (var item in ev)
                    {
                        if (append)
                        {
                            OutputChar(',');
                        }
                        WriteField(item._Name, item._Value);
                        append = true;
                    }
                }
                si.OnSerialized(obj);
            }
            #endregion

            _currentDepth--;
            OutputChar('}');
        }
Ejemplo n.º 4
0
 /// <summary>
 /// This method is called before deserializing a field or a property. If the method returns false, the member will not be deserialized.
 /// </summary>
 /// <param name="data">The container object.</param>
 /// <param name="item">The item to be deserialized.</param>
 /// <returns>Whether the member should be deserialized.</returns>
 public virtual bool OnDeserializing(T data, JsonItem item)
 {
     return(true);
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Returns the expected type for <paramref name="item"/>. The default implementation returns <typeparamref name="TSerialized"/>.
 /// </summary>
 /// <param name="item">The item to be deserialized.</param>
 /// <returns>The type of <typeparamref name="TSerialized"/>.</returns>
 public virtual Type GetReversiveType(JsonItem item)
 {
     return(_SerializedType);
 }
Ejemplo n.º 6
0
        object CreateList(JsonArray data, SerializationInfo info, object input)
        {
            var    listType = info;
            var    ec       = listType.TypeParameters != null ? listType.TypeParameters[0] : null;
            var    r        = listType.ItemDeserializeMethod;
            var    ic       = ec.Converter;
            object l        = input ?? info.Instantiate();
            IList  col      = l as IList;

            if (col != null)
            {
                if (ic != null)
                {
                    Type rt = null;
                    foreach (var item in data)
                    {
                        if (rt == null)
                        {
                            var ji = new JsonItem(null, item);
                            rt = ic.GetReversiveType(ji);
                        }
                        var xv = item;
                        if (xv != null && rt != null && ec.Reflection.Type.Equals(xv.GetType()) == false)
                        {
                            xv = RevertValueType(rt, xv);
                        }
                        xv = ic.DeserializationConvert(xv);
                        if (xv == null)
                        {
                            continue;
                        }
                        // TODO: determine whether item type is nullable
                        col.Add(xv != null ? r(this, xv, ec) : null);
                    }
                    return(col);
                }
                else if (r != null)
                {
                    foreach (var item in data)
                    {
                        // TODO: determine whether item type is nullable
                        col.Add(item != null ? r(this, item, ec) : null);
                    }
                    return(col);
                }
            }
            var a = listType.Reflection.AppendItem;

            if (a != null)
            {
                if (l == null)
                {
                    throw new JsonSerializationException("The collection member typed \"" + listType.Reflection.AssemblyName + "\" was null and could not be instantiated");
                }
                if (ic != null)
                {
                    Type rt = null;
                    foreach (var item in data)
                    {
                        if (rt == null)
                        {
                            var ji = new JsonItem(null, item);
                            rt = ic.GetReversiveType(ji);
                        }
                        var xv = item;
                        if (xv != null && rt != null && ec.Reflection.Type.Equals(xv.GetType()) == false)
                        {
                            xv = RevertValueType(rt, xv);
                        }
                        xv = ic.DeserializationConvert(xv);
                        if (xv == null)
                        {
                            continue;
                        }
                        a(l, r(this, item, ec));
                    }
                }
                else
                {
                    foreach (var item in data)
                    {
                        a(l, r(this, item, ec));
                    }
                }
                return(l);
            }
            return(col);
        }
Ejemplo n.º 7
0
        object CreateArray(JsonArray data, SerializationInfo arrayType)
        {
            var   l   = data.Count;
            var   ec  = arrayType.TypeParameters[0];
            Array col = Array.CreateInstance(ec.Reflection.Type, l);
            var   r   = arrayType.ItemDeserializeMethod;
            var   ic  = ec.Converter;

            if (r != null)
            {
                if (ic == null)
                {
                    for (int i = 0; i < l; i++)
                    {
                        var ob = data[i];
                        if (ob == null)
                        {
                            continue;
                        }
                        col.SetValue(r(this, ob, ec), i);
                    }
                }
                else
                {
                    Type rt = null;
                    for (int i = 0; i < l; i++)
                    {
                        var ob = data[i];
                        var ji = new JsonItem(null, ob);
                        if (rt == null)
                        {
                            rt = ic.GetReversiveType(ji);
                        }
                        var xv = ob;
                        if (xv != null && rt != null && ec.Reflection.Type.Equals(xv.GetType()) == false)
                        {
                            xv = RevertValueType(rt, xv);
                        }
                        ob = ic.DeserializationConvert(xv);
                        if (ob == null)
                        {
                            continue;
                        }
                        col.SetValue(r(this, ob, ec), i);
                    }
                }
                return(col);
            }

            // TODO: candidate of code clean-up
            // create an array of objects
            for (int i = 0; i < l; i++)
            {
                var ob = data[i];
                if (ob == null)
                {
                    continue;
                }
                if (ob is IDictionary)
                {
                    col.SetValue(CreateObject((JsonDict)ob, ec, null), i);
                }
                // support jagged array
                else if (ob is ICollection)
                {
                    col.SetValue(CreateArray((JsonArray)ob, ec), i);
                }
                else
                {
                    col.SetValue(ChangeType(ob, ec.Reflection.Type), i);
                }
            }

            return(col);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Deserializes an object.
        /// </summary>
        /// <param name="data">The data to be deserialized.</param>
        /// <param name="type">The reflection cache of the type.</param>
        /// <param name="input">The data container. If this value is not null, deserialized members will be written to it. If null, new object will be created.</param>
        /// <returns>The deserialized object.</returns>
        /// <exception cref="JsonSerializationException">Cannot determine type from <paramref name="data"/>.</exception>
        internal object CreateObject(JsonDict data, SerializationInfo type, object input)
        {
            if (data.RefIndex > 0)
            {
                object v = null;
                _cirrev.TryGetValue(data.RefIndex, out v);
                return(v);
            }

            if (String.IsNullOrEmpty(data.Type) == false)
            {
                type = _manager.GetSerializationInfo(data.Type);
                if (type == null)
                {
                    type = _manager.GetSerializationInfo(Reflection.GetTypeFromCache(data.Type));
                }
            }
            if (type != null && typeof(object).Equals(type.Reflection.Type))
            {
                return(data);
            }

            if (type == null)
            {
                throw new JsonSerializationException("Cannot determine type");
            }

            object o = input;

            if (o == null)
            {
                o = _manager.ParametricConstructorOverride
                                        ? System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type.Reflection.Type)
                                        : type.Instantiate();
            }
            int circount = 0;

            // dictionary lookup makes it impossible to use objects with a custom GetHashCode based on (unchanging) properties:
            if (_circobj.TryGetValue(o, out circount) == false)
            {
                circount = _circobj.Count + 1;
                _circobj.Add(o, circount);
                _cirrev.Add(circount, o);
            }

            var si = type.Interceptor;

            if (si != null)
            {
                si.OnDeserializing(o);
            }
            var props = type.Setters;

            foreach (var kv in data)
            {
                var n = kv.Key;
                var v = kv.Value;
                JsonMemberSetter pi;
                // field name is not defined
                if (props.TryGetValue(n, out pi) == false)
                {
                    continue;
                }
                if (pi.CanWrite == false && pi.Member.JsonDataType != JsonDataType.List)
                {
                    continue;
                }
                var  m         = pi.Member;
                var  ji        = new JsonItem(n, v, false);
                bool converted = false;
                // TODO: Convert items for types implements IEnumerable and Add(?) method
                if (v is IList && pi.ItemConverter != null)
                {
                    ji._Value = ConvertItems(pi, v as IList);
                }
                if (pi.Converter != null || pi.TypeInfo.Converter != null)
                {
                    ConvertProperty(o, pi, ji);
                }

                object oset = null;
                // use the converted value
                if (converted || ReferenceEquals(ji._Value, v) == false)
                {
                    if (pi.CanWrite == false && m.JsonDataType == JsonDataType.List)
                    {
                        ji._Value = CreateList((JsonArray)ji._Value, pi.TypeInfo, m.Getter(o));
                    }
                    if (ji._Value != null || m.IsClass || m.IsNullable)
                    {
                        oset = ji._Value;
                        goto SET_VALUE;
                    }
                    continue;
                }
                // process null value
                if (ji._Value == null)
                {
                    var i = new JsonItem(n, null, false);
                    if (si != null && si.OnDeserializing(o, i) == false)
                    {
                        continue;
                    }
                    if (i.Value != null || m.IsClass || m.IsNullable)
                    {
                        o = m.Setter(o, i.Value);
                    }
                    continue;
                }
                v = ji._Value;
                // set member value
                switch (m.JsonDataType)
                {
                case JsonDataType.Undefined: goto default;

                case JsonDataType.Int: oset = v is long?(int)(long)v : v is double?(int)(double)v : v is string?ValueConverter.ToInt32((string)v) : v is bool && (bool)v ? 1 : 0; break;

                case JsonDataType.String: oset = v is string?(string)v: v is double?((double)v).ToString() : v is long?ValueConverter.Int64ToString((long)v) : v is bool?((bool)v).ToString() : null; break;

                case JsonDataType.Bool: oset = v is bool?(bool)v : v is double?(double)v != 0 : v is long?(long)v != 0 : v is string?ValueConverter.ToBoolean((string)v) : false; break;

                case JsonDataType.Long: oset = v is long?(long)v : v is double?(long)(double)v : v is string?ValueConverter.ToInt64((string)v) : v is bool && (bool)v ? 1L : 0L; break;

                case JsonDataType.Double: oset = v is double?(double)v: v is long?(double)(long)v : v is string?ValueConverter.ToDouble((string)v) : v is bool && (bool)v ? 1D : 0D; break;

                case JsonDataType.Single: oset = v is double?(float)(double)v: v is long?(float)(long)v : v is string?ValueConverter.ToSingle((string)v) : v is bool && (bool)v ? 1F : 0F; break;

                case JsonDataType.DateTime: oset = CreateDateTime(this, v); break;

                case JsonDataType.Guid: oset = CreateGuid(v); break;

                case JsonDataType.ByteArray: oset = Convert.FromBase64String((string)v); break;

                case JsonDataType.List:
                    if (pi.TypeInfo.CollectionName != null)
                    {
                        goto default;
                    }
                    oset = CreateList((JsonArray)v, pi.TypeInfo, pi.CanWrite && (m.IsClass || m.IsStruct) ? null : m.Getter(o));
                    break;

                case JsonDataType.Object: oset = v; break;

                default:
                    if (pi.TypeInfo.DeserializeMethod != null)
                    {
                        oset = pi.TypeInfo.DeserializeMethod(this, ji._Value, pi.TypeInfo);
                        goto SET_VALUE;
                    }
                    if ((m.IsClass || m.IsStruct) && v is JsonDict)
                    {
                        oset = CreateObject((JsonDict)v, pi.TypeInfo, m.Getter(o));
                    }

                    else if (v is JsonArray)
                    {
                        oset = CreateArray((JsonArray)v, _manager.GetSerializationInfo(typeof(object[])));
                    }

                    else if (m.IsValueType)
                    {
                        oset = ChangeType(v, m.ChangeType);
                    }

                    else
                    {
                        oset = v;
                    }

                    break;
                }
SET_VALUE:
                ji.Value = oset;
                if (si != null)
                {
                    if (si.OnDeserializing(o, ji) == false)
                    {
                        continue;
                    }
                }
                if (m.Setter != null)
                {
                    //try {
                    o = m.Setter(o, ji.Value);
                    //}
                    //catch (InvalidCastException) {
                    //	if (_manager.SetDefaultForMismatchedProperty) {
                    //		o = m.Setter(o, m.IsValueType ? System.Runtime.Serialization.FormatterServices.GetUninitializedObject(m.MemberType) : null);
                    //		Console.WriteLine("Error when setting " + m.MemberName);
                    //		continue;
                    //	}
                    //	throw;
                    //}
                }
            }
            if (si != null)
            {
                si.OnDeserialized(o);
            }
            return(o);
        }