Esempio n. 1
0
        protected virtual void Write(object value, bool isProperty, Type fieldType = null)
        {
            if (isProperty && this.settings.PrettyPrint)
            {
                this.Writer.Write(' ');
            }

            if (value == null)
            {
                this.Writer.Write(JsonReader.LiteralNull);
                return;
            }

            if (value is IJsonSerializable)
            {
                try
                {
                    if (isProperty)
                    {
                        this.depth++;
                        if (this.depth > this.settings.MaxDepth)
                        {
                            throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, new System.Object[] { this.settings.MaxDepth }));
                        }
                        this.WriteLine();
                    }
                    ((IJsonSerializable)value).WriteJson(this);
                }
                finally
                {
                    if (isProperty)
                    {
                        this.depth--;
                    }
                }
                return;
            }

            // must test enumerations before value types
            if (value is Enum)
            {
                this.Write((Enum)value);
                return;
            }

            // Type.GetTypeCode() allows us to more efficiently switch type
            // plus cannot use 'is' for ValueTypes
            Type type = value.GetType();

#if WINDOWS_STORE
            if (Type.Equals(type, typeof(bool)))
            {
                this.Write((Boolean)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.Int32)))
            {
                this.Write((Int32)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.Single)))
            {
                this.Write((Single)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.String)))
            {
                this.Write((String)value);
                return;
            }
            else if (Type.Equals(type, typeof(byte)))
            {
                this.Write((Byte)value);
                return;
            }
            else if (Type.Equals(type, typeof(char)))
            {
                this.Write((Char)value);
                return;
            }
            else if (Type.Equals(type, typeof(DateTime)))
            {
                this.Write((DateTime)value);
                return;
            }
            else if (Type.Equals(type, typeof(DBNull)) || Type.Equals(type, null))
            {
                this.Writer.Write(JsonReader.LiteralNull);
                return;
            }
            else if (Type.Equals(type, typeof(Decimal)))
            {
                // From MSDN:
                // Conversions from Char, SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, and UInt64
                // to Decimal are widening conversions that never lose information or throw exceptions.
                // Conversions from Single or Double to Decimal throw an OverflowException
                // if the result of the conversion is not representable as a Decimal.
                this.Write((Decimal)value);
                return;
            }
            else if (Type.Equals(type, typeof(double)))
            {
                this.Write((Double)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.Int16)))
            {
                this.Write((Int16)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.Int64)))
            {
                this.Write((Int64)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.SByte)))
            {
                this.Write((SByte)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.UInt16)))
            {
                this.Write((UInt16)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.UInt32)))
            {
                this.Write((UInt32)value);
                return;
            }
            else if (Type.Equals(type, typeof(System.UInt64)))
            {
                this.Write((UInt64)value);
                return;
            }
            else
            {
                // all others must be explicitly tested
            }
#else
            // Faster to switch on typecode, but Windows Store does not support it
            switch (TP.GetTypeCode(type))
            {
            case TypeCode.Boolean:
            {
                this.Write((Boolean)value);
                return;
            }

            case TypeCode.Byte:
            {
                this.Write((Byte)value);
                return;
            }

            case TypeCode.Char:
            {
                this.Write((Char)value);
                return;
            }

            case TypeCode.DateTime:
            {
                this.Write((DateTime)value);
                return;
            }

            case TypeCode.DBNull:
            case TypeCode.Empty:
            {
                this.Writer.Write(JsonReader.LiteralNull);
                return;
            }

            case TypeCode.Decimal:
            {
                // From MSDN:
                // Conversions from Char, SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, and UInt64
                // to Decimal are widening conversions that never lose information or throw exceptions.
                // Conversions from Single or Double to Decimal throw an OverflowException
                // if the result of the conversion is not representable as a Decimal.
                this.Write((Decimal)value);
                return;
            }

            case TypeCode.Double:
            {
                this.Write((Double)value);
                return;
            }

            case TypeCode.Int16:
            {
                this.Write((Int16)value);
                return;
            }

            case TypeCode.Int32:
            {
                this.Write((Int32)value);
                return;
            }

            case TypeCode.Int64:
            {
                this.Write((Int64)value);
                return;
            }

            case TypeCode.SByte:
            {
                this.Write((SByte)value);
                return;
            }

            case TypeCode.Single:
            {
                this.Write((Single)value);
                return;
            }

            case TypeCode.String:
            {
                this.Write((String)value);
                return;
            }

            case TypeCode.UInt16:
            {
                this.Write((UInt16)value);
                return;
            }

            case TypeCode.UInt32:
            {
                this.Write((UInt32)value);
                return;
            }

            case TypeCode.UInt64:
            {
                this.Write((UInt64)value);
                return;
            }

            default:
            case TypeCode.Object:
            {
                // all others must be explicitly tested
                break;
            }
            }
#endif

            JsonConverter converter = this.Settings.GetConverter(type);
            if (converter != null && (depth != 0 || converter.convertAtDepthZero))
            {
                converter.Write(this, type, value);
                return;
            }

            if (value is Guid)
            {
                this.Write((Guid)value);
                return;
            }

            if (value is Uri)
            {
                this.Write((Uri)value);
                return;
            }

            if (value is TimeSpan)
            {
                this.Write((TimeSpan)value);
                return;
            }

            if (value is Version)
            {
                this.Write((Version)value);
                return;
            }

            // IDictionary test must happen BEFORE IEnumerable test
            // since IDictionary implements IEnumerable
            if (value is IDictionary)
            {
                try
                {
                    if (isProperty)
                    {
                        this.depth++;
                        if (this.depth > this.settings.MaxDepth)
                        {
                            throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, new System.Object[] { this.settings.MaxDepth }));
                        }
                        this.WriteLine();
                    }
                    this.WriteObject((IDictionary)value);
                }
                finally
                {
                    if (isProperty)
                    {
                        this.depth--;
                    }
                }
                return;
            }

            //if (!Type.Equals (TCU.GetTypeInfo(type).GetInterface (JsonReader.TypeGenericIDictionary), null))
            if (TCU.GetTypeInfo(typeof(IDictionary)).IsAssignableFrom(TCU.GetTypeInfo(value.GetType())))
            {
                try {
                    if (isProperty)
                    {
                        this.depth++;
                        if (this.depth > this.settings.MaxDepth)
                        {
                            throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, new System.Object[] { this.settings.MaxDepth }));
                        }
                        this.WriteLine();
                    }

                    this.WriteDictionary((IEnumerable)value);
                } finally {
                    if (isProperty)
                    {
                        this.depth--;
                    }
                }
                return;
            }

            if (value is IList && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>))
            {
                // Is List<T>
                var memberType = type.GetGenericArguments() [0];

                try
                {
                    if (isProperty)
                    {
                        this.depth++;
                        if (this.depth > this.settings.MaxDepth)
                        {
                            throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, new System.Object[] { this.settings.MaxDepth }));
                        }
                        this.WriteLine();
                    }

                    this.WriteArray((IEnumerable)value, memberType);
                }
                finally
                {
                    if (isProperty)
                    {
                        this.depth--;
                    }
                }
                return;
            }

            // IDictionary test must happen BEFORE IEnumerable test
            // since IDictionary implements IEnumerable
            if (value is IEnumerable)
            {
#if !UNITY3D
                if (value is XmlNode)
                {
                    this.Write((System.Xml.XmlNode)value);
                    return;
                }
#endif
                try
                {
                    if (isProperty)
                    {
                        this.depth++;
                        if (this.depth > this.settings.MaxDepth)
                        {
                            throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, new System.Object[] { this.settings.MaxDepth }));
                        }
                        this.WriteLine();
                    }

                    this.WriteArray((IEnumerable)value, type.GetElementType());
                }
                finally
                {
                    if (isProperty)
                    {
                        this.depth--;
                    }
                }
                return;
            }

            // structs and classes
            try
            {
                if (isProperty)
                {
                    this.depth++;
                    if (this.depth > this.settings.MaxDepth)
                    {
                        throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, new System.Object[] { this.settings.MaxDepth }));
                    }
                    this.WriteLine();
                }
                this.WriteObject(value, type, true, fieldType);
            }
            finally
            {
                if (isProperty)
                {
                    this.depth--;
                }
            }
        }