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--; } } }