/** Adds a converter to use to serialize otherwise non-serializable types. * Good if you do not have the source and it throws error when trying to serialize it. * For example the Unity3D Vector3 can be serialized using a special converter */ public virtual void AddTypeConverter (JsonConverter converter) { converters.Add (converter); }
public virtual void AddTypeConverter(JsonConverter converter) { converters.Add(converter); }
protected virtual void Write(object value, bool isProperty) { 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("The maxiumum depth of {0} was exceeded. Check for cycles in object graph.", this.settings.MaxDepth)); } this.WriteLine(); } ((IJsonSerializable)value).WriteJson(this); } finally { if (isProperty) { this.depth--; } } return; } if (value is Enum) { this.Write((Enum)value); return; } Type type = value.GetType(); JsonConverter converter = this.Settings.GetConverter(type); if (converter != null) { converter.Write(this, type, value); return; } switch (Type.GetTypeCode(type)) { case TypeCode.Empty: case TypeCode.DBNull: this.Writer.Write(JsonReader.LiteralNull); return; case TypeCode.Boolean: this.Write((bool)value); return; case TypeCode.Char: this.Write((char)value); return; case TypeCode.SByte: this.Write((sbyte)value); return; case TypeCode.Byte: this.Write((byte)value); return; case TypeCode.Int16: this.Write((short)value); return; case TypeCode.UInt16: this.Write((ushort)value); return; case TypeCode.Int32: this.Write((int)value); return; case TypeCode.UInt32: this.Write((uint)value); return; case TypeCode.Int64: this.Write((long)value); return; case TypeCode.UInt64: this.Write((ulong)value); return; case TypeCode.Single: this.Write((float)value); return; case TypeCode.Double: this.Write((double)value); return; case TypeCode.Decimal: this.Write((decimal)value); return; case TypeCode.DateTime: this.Write((DateTime)value); return; case TypeCode.String: this.Write((string)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; } if (value is IDictionary) { try { if (isProperty) { this.depth++; if (this.depth > this.settings.MaxDepth) { throw new JsonSerializationException(string.Format("The maxiumum depth of {0} was exceeded. Check for cycles in object graph.", this.settings.MaxDepth)); } this.WriteLine(); } this.WriteObject((IDictionary)value); } finally { if (isProperty) { this.depth--; } } return; } if (type.GetInterface(JsonReader.TypeGenericIDictionary) != null) { try { if (isProperty) { this.depth++; if (this.depth > this.settings.MaxDepth) { throw new JsonSerializationException(string.Format("The maxiumum depth of {0} was exceeded. Check for cycles in object graph.", this.settings.MaxDepth)); } this.WriteLine(); } this.WriteDictionary((IEnumerable)value); } finally { if (isProperty) { this.depth--; } } return; } if (value is IEnumerable) { try { if (isProperty) { this.depth++; if (this.depth > this.settings.MaxDepth) { throw new JsonSerializationException(string.Format("The maxiumum depth of {0} was exceeded. Check for cycles in object graph.", this.settings.MaxDepth)); } this.WriteLine(); } this.WriteArray((IEnumerable)value); } finally { if (isProperty) { this.depth--; } } return; } try { if (isProperty) { this.depth++; if (this.depth > this.settings.MaxDepth) { throw new JsonSerializationException(string.Format("The maxiumum depth of {0} was exceeded. Check for cycles in object graph.", this.settings.MaxDepth)); } this.WriteLine(); } this.WriteObject(value, type, false); } finally { if (isProperty) { this.depth--; } } }
protected virtual void Write(object value, bool isProperty) { 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, 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(); JsonConverter converter = this.Settings.GetConverter(type); if (converter != null) { converter.Write(this, type, value); return; } #if NETFX_CORE switch (type.GetTypeCode()) #else switch (Type.GetTypeCode(type)) #endif { 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; } } 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, this.settings.MaxDepth)); } this.WriteLine(); } this.WriteObject((IDictionary)value); } finally { if (isProperty) { this.depth--; } } return; } if (type.GetInterface(JsonReader.TypeGenericIDictionary, false) != null) { try { if (isProperty) { this.depth++; if (this.depth > this.settings.MaxDepth) { throw new JsonSerializationException(String.Format(JsonWriter.ErrorMaxDepth, this.settings.MaxDepth)); } this.WriteLine(); } this.WriteDictionary((IEnumerable)value); } 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, this.settings.MaxDepth)); } this.WriteLine(); } this.WriteArray((IEnumerable)value); } 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, this.settings.MaxDepth)); } this.WriteLine(); } this.WriteObject(value, type); } finally { if (isProperty) { this.depth--; } } }
/// <summary> /// Convert from JSON string to Object graph of specific Type /// </summary> /// <param name="type"></param> /// <returns></returns> /*public T Deserialize<T>(int start) * { * this.index = start; * * // should this run through a preliminary test here? * return (T)this.Read(typeof(T), false); * }*/ private object Read(Type expectedType, bool typeIsHint) { if (expectedType == typeof(Object)) { expectedType = null; } JsonToken token = this.Tokenize(); if (expectedType != null && !expectedType.IsPrimitive) { JsonConverter converter = this.Settings.GetConverter(expectedType); if (converter != null) { object val; try { val = Read(typeof(Dictionary <string, object>), false); Dictionary <string, object> dict = val as Dictionary <string, object>; if (dict == null) { return(null); } object obj = converter.Read(this, expectedType, dict); return(obj); } catch (JsonTypeCoercionException e) { Console.WriteLine("Could not cast to dictionary for converter processing. Ignoring field.\n" + e); } return(null); } } switch (token) { case JsonToken.ObjectStart: { return(this.ReadObject(typeIsHint ? null : expectedType)); } case JsonToken.ArrayStart: { return(this.ReadArray(typeIsHint ? null : expectedType)); } case JsonToken.String: { return(this.ReadString(typeIsHint ? null : expectedType)); } case JsonToken.Number: { return(this.ReadNumber(typeIsHint ? null : expectedType)); } case JsonToken.False: { this.index += JsonReader.LiteralFalse.Length; return(false); } case JsonToken.True: { this.index += JsonReader.LiteralTrue.Length; return(true); } case JsonToken.Null: { this.index += JsonReader.LiteralNull.Length; return(null); } case JsonToken.NaN: { this.index += JsonReader.LiteralNotANumber.Length; return(Double.NaN); } case JsonToken.PositiveInfinity: { this.index += JsonReader.LiteralPositiveInfinity.Length; return(Double.PositiveInfinity); } case JsonToken.NegativeInfinity: { this.index += JsonReader.LiteralNegativeInfinity.Length; return(Double.NegativeInfinity); } case JsonToken.Undefined: { this.index += JsonReader.LiteralUndefined.Length; return(null); } case JsonToken.End: default: { return(null); } } }