From b5e7005735e5539dc57588b3eb7496a192b0397e Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 1 Apr 2013 12:38:45 +1300 Subject: [PATCH] -Added support for serializing custom IConvertible values -Refactored away dependency on IConvertible --- .../JsonTextWriterTest.cs | 106 ++++++ Src/Newtonsoft.Json.Tests/PerformanceTests.cs | 2 +- .../Serialization/JsonSerializerTest.cs | 44 ++- .../Converters/StringEnumConverter.cs | 1 + Src/Newtonsoft.Json/JsonConvert.cs | 164 +++------ Src/Newtonsoft.Json/JsonReader.cs | 4 +- Src/Newtonsoft.Json/JsonTextWriter.cs | 28 +- Src/Newtonsoft.Json/JsonWriter.cs | 334 +++++++++--------- Src/Newtonsoft.Json/Linq/JToken.cs | 157 ++++---- .../Schema/JsonSchemaGenerator.cs | 51 +-- .../Serialization/DefaultContractResolver.cs | 2 +- .../Serialization/JsonContract.cs | 3 - .../Serialization/JsonPrimitiveContract.cs | 304 +--------------- .../JsonSerializerInternalReader.cs | 12 +- .../JsonSerializerInternalWriter.cs | 49 +-- Src/Newtonsoft.Json/Utilities/ConvertUtils.cs | 331 ++++++++--------- .../Utilities/ReflectionUtils.cs | 69 ++-- 17 files changed, 704 insertions(+), 957 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs index 5387b6ca..18aa1862 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs @@ -63,6 +63,16 @@ namespace Newtonsoft.Json.Tests writer.Close(); Assert.IsTrue(ms.CanRead); } + + [Test] + public void WriteIConvertable() + { + var sw = new StringWriter(); + JsonTextWriter writer = new JsonTextWriter(sw); + writer.WriteValue(new ConvertibleInt(1)); + + Assert.AreEqual("1", sw.ToString()); + } [Test] public void ValueFormatting() @@ -1260,7 +1270,103 @@ _____'propertyName': NaN if (appendDelimiters) writer.Write(delimiter); } + } + public struct ConvertibleInt : IConvertible + { + private readonly int _value; + public ConvertibleInt(int value) + { + _value = value; + } + + public TypeCode GetTypeCode() + { + return TypeCode.Int32; + } + + public bool ToBoolean(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public byte ToByte(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public char ToChar(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public DateTime ToDateTime(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public decimal ToDecimal(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public double ToDouble(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public short ToInt16(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public int ToInt32(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public long ToInt64(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public sbyte ToSByte(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public float ToSingle(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public string ToString(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public object ToType(Type conversionType, IFormatProvider provider) + { + if (conversionType == typeof(int)) + return _value; + + throw new Exception("Type not supported: " + conversionType.FullName); + } + + public ushort ToUInt16(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public uint ToUInt32(IFormatProvider provider) + { + throw new NotImplementedException(); + } + + public ulong ToUInt64(IFormatProvider provider) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index fc477b2c..591f86f8 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -100,7 +100,7 @@ namespace Newtonsoft.Json.Tests DataContractJsonSerializer } - #endregion +#endregion [Test] public void SerializeSimpleObject() diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 42259ace..d96ac16e 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -5762,6 +5762,46 @@ To fix this error either change the environment to be fully trusted, change the }); } + public class ConvertableIntTestClass + { + public ConvertibleInt Integer { get; set; } + public ConvertibleInt? NullableInteger1 { get; set; } + public ConvertibleInt? NullableInteger2 { get; set; } + } + + [Test] + public void SerializeIConvertible() + { + ConvertableIntTestClass c = new ConvertableIntTestClass + { + Integer = new ConvertibleInt(1), + NullableInteger1 = new ConvertibleInt(2), + NullableInteger2 = null + }; + + string json = JsonConvert.SerializeObject(c, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Integer"": 1, + ""NullableInteger1"": 2, + ""NullableInteger2"": null +}", json); + } + + [Test] + public void DeserializeIConvertible() + { + string json = @"{ + ""Integer"": 1, + ""NullableInteger1"": 2, + ""NullableInteger2"": null +}"; + + ExceptionAssert.Throws( + "Error converting value 1 to type 'Newtonsoft.Json.Tests.ConvertibleInt'. Path 'Integer', line 2, position 15.", + () => JsonConvert.DeserializeObject(json)); + } + [Test] public void SerializeNullableWidgetStruct() { @@ -6352,7 +6392,7 @@ Parameter name: value", [Test] public void DateTimeDictionaryKey_DateTimeOffset_MS() { - IDictionary dic1 = new Dictionary + IDictionary dic1 = new Dictionary { {new DateTimeOffset(2000, 12, 12, 12, 12, 12, TimeSpan.Zero), 1}, {new DateTimeOffset(2013, 12, 12, 12, 12, 12, TimeSpan.Zero), 2} @@ -6368,7 +6408,7 @@ Parameter name: value", ""\/Date(1386850332000+0000)\/"": 2 }", json); - IDictionary dic2 = JsonConvert.DeserializeObject>(json); + IDictionary dic2 = JsonConvert.DeserializeObject>(json); Assert.AreEqual(2, dic2.Count); Assert.AreEqual(1, dic2[new DateTimeOffset(2000, 12, 12, 12, 12, 12, TimeSpan.Zero)]); diff --git a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs index 39001f8d..1cb6cac4 100644 --- a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -70,6 +70,7 @@ namespace Newtonsoft.Json.Converters if (char.IsNumber(enumName[0]) || enumName[0] == '-') { + // enum value has no name so write number writer.WriteValue(value); } else diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index f58842fc..852b1c11 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -32,6 +32,7 @@ using System.Numerics; #if !(NET20 || NET35 || SILVERLIGHT) using System.Threading.Tasks; #endif +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; using System.Xml; using Newtonsoft.Json.Converters; @@ -39,9 +40,6 @@ using System.Text; #if !NET20 && (!SILVERLIGHT || WINDOWS_PHONE) using System.Xml.Linq; #endif -#if NETFX_CORE || PORTABLE -using IConvertible = Newtonsoft.Json.Utilities.Convertible; -#endif namespace Newtonsoft.Json { @@ -625,127 +623,77 @@ namespace Newtonsoft.Json if (value == null) return Null; - IConvertible convertible = ConvertUtils.ToConvertible(value); + PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value); - if (convertible != null) + switch (typeCode) { - switch (convertible.GetTypeCode()) - { - case TypeCode.String: - return ToString(convertible.ToString(CultureInfo.InvariantCulture)); - case TypeCode.Char: - return ToString(convertible.ToChar(CultureInfo.InvariantCulture)); - case TypeCode.Boolean: - return ToString(convertible.ToBoolean(CultureInfo.InvariantCulture)); - case TypeCode.SByte: - return ToString(convertible.ToSByte(CultureInfo.InvariantCulture)); - case TypeCode.Int16: - return ToString(convertible.ToInt16(CultureInfo.InvariantCulture)); - case TypeCode.UInt16: - return ToString(convertible.ToUInt16(CultureInfo.InvariantCulture)); - case TypeCode.Int32: - return ToString(convertible.ToInt32(CultureInfo.InvariantCulture)); - case TypeCode.Byte: - return ToString(convertible.ToByte(CultureInfo.InvariantCulture)); - case TypeCode.UInt32: - return ToString(convertible.ToUInt32(CultureInfo.InvariantCulture)); - case TypeCode.Int64: - return ToString(convertible.ToInt64(CultureInfo.InvariantCulture)); - case TypeCode.UInt64: - return ToString(convertible.ToUInt64(CultureInfo.InvariantCulture)); - case TypeCode.Single: - return ToString(convertible.ToSingle(CultureInfo.InvariantCulture)); - case TypeCode.Double: - return ToString(convertible.ToDouble(CultureInfo.InvariantCulture)); - case TypeCode.DateTime: - return ToString(convertible.ToDateTime(CultureInfo.InvariantCulture)); - case TypeCode.Decimal: - return ToString(convertible.ToDecimal(CultureInfo.InvariantCulture)); + case PrimitiveTypeCode.String: + return ToString((string) value); + case PrimitiveTypeCode.Char: + return ToString((char) value); + case PrimitiveTypeCode.Boolean: + return ToString((bool) value); + case PrimitiveTypeCode.SByte: + return ToString((sbyte) value); + case PrimitiveTypeCode.Int16: + return ToString((short) value); + case PrimitiveTypeCode.UInt16: + return ToString((ushort) value); + case PrimitiveTypeCode.Int32: + return ToString((int) value); + case PrimitiveTypeCode.Byte: + return ToString((byte) value); + case PrimitiveTypeCode.UInt32: + return ToString((uint) value); + case PrimitiveTypeCode.Int64: + return ToString((long) value); + case PrimitiveTypeCode.UInt64: + return ToString((ulong) value); + case PrimitiveTypeCode.Single: + return ToString((float) value); + case PrimitiveTypeCode.Double: + return ToString((double) value); + case PrimitiveTypeCode.DateTime: + return ToString((DateTime) value); + case PrimitiveTypeCode.Decimal: + return ToString((decimal) value); #if !(NETFX_CORE || PORTABLE) - case TypeCode.DBNull: - return Null; + case PrimitiveTypeCode.DBNull: + return Null; #endif - } - } #if !NET20 - else if (value is DateTimeOffset) - { - return ToString((DateTimeOffset) value); - } + case PrimitiveTypeCode.DateTimeOffset: + return ToString((DateTimeOffset) value); #endif - else if (value is Guid) - { - return ToString((Guid) value); - } - else if (value is Uri) - { - return ToString((Uri) value); - } - else if (value is TimeSpan) - { - return ToString((TimeSpan) value); - } + case PrimitiveTypeCode.Guid: + return ToString((Guid) value); + case PrimitiveTypeCode.Uri: + return ToString((Uri) value); + case PrimitiveTypeCode.TimeSpan: + return ToString((TimeSpan) value); #if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) - else if (value is BigInteger) - { - return ToString((BigInteger) value); - } + case PrimitiveTypeCode.BigInteger: + return ToString((BigInteger) value); #endif + } throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } - private static bool IsJsonPrimitiveTypeCode(TypeCode typeCode) + internal static bool IsJsonPrimitiveType(Type t) { - switch (typeCode) + PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(t); + + if (typeCode != PrimitiveTypeCode.Empty && typeCode != PrimitiveTypeCode.Object) + return true; + + if (typeof(IConvertible).IsAssignableFrom(t) + || (ReflectionUtils.IsNullableType(t) && typeof(IConvertible).IsAssignableFrom(Nullable.GetUnderlyingType(t)))) { - case TypeCode.String: - case TypeCode.Char: - case TypeCode.Boolean: - case TypeCode.SByte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.Byte: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.DateTime: - case TypeCode.Decimal: -#if !(NETFX_CORE || PORTABLE) - case TypeCode.DBNull: -#endif - return true; - default: - return false; + return !typeof(JToken).IsAssignableFrom(t); } - } - internal static bool IsJsonPrimitiveType(Type type) - { - if (ReflectionUtils.IsNullableType(type)) - type = Nullable.GetUnderlyingType(type); - -#if !NET20 - if (type == typeof (DateTimeOffset)) - return true; -#endif - if (type == typeof (byte[])) - return true; - if (type == typeof (Uri)) - return true; - if (type == typeof (TimeSpan)) - return true; - if (type == typeof (Guid)) - return true; -#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) - if (type == typeof (BigInteger)) - return true; -#endif - - return IsJsonPrimitiveTypeCode(ConvertUtils.GetTypeCode(type)); + return false; } internal static bool TryParseDateTime(string s, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, out object dt) diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index 49bba741..faa66061 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -621,9 +621,7 @@ namespace Newtonsoft.Json if (Value != null) { string s; - if (ConvertUtils.IsConvertible(Value)) - s = ConvertUtils.ToConvertible(Value).ToString(Culture); - else if (Value is IFormattable) + if (Value is IFormattable) s = ((IFormattable)Value).ToString(null, Culture); else s = Value.ToString(); diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 3ab5f32b..62505d9c 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -47,6 +47,7 @@ namespace Newtonsoft.Json private int _indentation; private char _quoteChar; private bool _quoteName; + private bool[] _charEscapeFlags; private Base64Encoder Base64Encoder { @@ -86,6 +87,7 @@ namespace Newtonsoft.Json throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and ""."); _quoteChar = value; + UpdateCharEscapeFlags(); } } @@ -121,6 +123,8 @@ namespace Newtonsoft.Json _quoteName = true; _indentChar = ' '; _indentation = 2; + + UpdateCharEscapeFlags(); } /// @@ -209,7 +213,7 @@ namespace Newtonsoft.Json { InternalWritePropertyName(name); - JavaScriptUtils.WriteEscapedJavaScriptString(_writer, name, _quoteChar, _quoteName, GetCharEscapeFlags(), StringEscapeHandling); + JavaScriptUtils.WriteEscapedJavaScriptString(_writer, name, _quoteChar, _quoteName, _charEscapeFlags, StringEscapeHandling); _writer.Write(':'); } @@ -225,7 +229,7 @@ namespace Newtonsoft.Json if (escape) { - JavaScriptUtils.WriteEscapedJavaScriptString(_writer, name, _quoteChar, _quoteName, GetCharEscapeFlags(), StringEscapeHandling); + JavaScriptUtils.WriteEscapedJavaScriptString(_writer, name, _quoteChar, _quoteName, _charEscapeFlags, StringEscapeHandling); } else { @@ -241,15 +245,19 @@ namespace Newtonsoft.Json _writer.Write(':'); } - private bool[] GetCharEscapeFlags() + internal override void OnStringEscapeHandlingChanged() + { + UpdateCharEscapeFlags(); + } + + private void UpdateCharEscapeFlags() { if (StringEscapeHandling == StringEscapeHandling.EscapeHtml) - return JavaScriptUtils.HtmlCharEscapeFlags; - - if (_quoteChar == '"') - return JavaScriptUtils.DoubleQuoteCharEscapeFlags; - - return JavaScriptUtils.SingleQuoteCharEscapeFlags; + _charEscapeFlags = JavaScriptUtils.HtmlCharEscapeFlags; + else if (_quoteChar == '"') + _charEscapeFlags = JavaScriptUtils.DoubleQuoteCharEscapeFlags; + else + _charEscapeFlags = JavaScriptUtils.SingleQuoteCharEscapeFlags; } /// @@ -335,7 +343,7 @@ namespace Newtonsoft.Json if (value == null) WriteValueInternal(JsonConvert.Null, JsonToken.Null); else - JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, true, GetCharEscapeFlags(), StringEscapeHandling); + JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, true, _charEscapeFlags, StringEscapeHandling); } /// diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index b4258909..d5f390ff 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -31,9 +31,6 @@ using System.Numerics; #endif using Newtonsoft.Json.Utilities; using System.Globalization; -#if NETFX_CORE || PORTABLE -using IConvertible = Newtonsoft.Json.Utilities.Convertible; -#endif #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -250,7 +247,16 @@ namespace Newtonsoft.Json public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling; } - set { _stringEscapeHandling = value; } + set + { + _stringEscapeHandling = value; + OnStringEscapeHandlingChanged(); + } + } + + internal virtual void OnStringEscapeHandlingChanged() + { + // hacky but there is a calculated value that relies on StringEscapeHandling } /// @@ -1254,176 +1260,11 @@ namespace Newtonsoft.Json /// /// The value to write. public virtual void WriteValue(object value) - { - WriteValueInternal(value, false); - } - - /// - /// Writes a value. - /// An error will raised if the value cannot be written as a single JSON token. - /// - /// The value to write. - /// A flag indicating whether the value is nullable. - public virtual void WriteValue(object value, bool nullable) - { - WriteValueInternal(value, nullable); - } - - private void WriteValueInternal(object value, bool nullable) { if (value == null) - { WriteNull(); - return; - } - - IConvertible convertible = ConvertUtils.ToConvertible(value); - if (convertible != null) - { - switch (convertible.GetTypeCode()) - { - case TypeCode.String: - WriteValue(convertible.ToString(CultureInfo.InvariantCulture)); - return; - case TypeCode.Char: - if (nullable) - WriteValue((char?)convertible.ToChar(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToChar(CultureInfo.InvariantCulture)); - return; - case TypeCode.Boolean: - if (nullable) - WriteValue((bool?)convertible.ToBoolean(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToBoolean(CultureInfo.InvariantCulture)); - return; - case TypeCode.SByte: - if (nullable) - WriteValue((sbyte?)convertible.ToSByte(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToSByte(CultureInfo.InvariantCulture)); - return; - case TypeCode.Int16: - if (nullable) - WriteValue((short?)convertible.ToInt16(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToInt16(CultureInfo.InvariantCulture)); - return; - case TypeCode.UInt16: - if (nullable) - WriteValue((ushort?)convertible.ToUInt16(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToUInt16(CultureInfo.InvariantCulture)); - return; - case TypeCode.Int32: - if (nullable) - WriteValue((int?)convertible.ToInt32(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToInt32(CultureInfo.InvariantCulture)); - return; - case TypeCode.Byte: - if (nullable) - WriteValue((byte?)convertible.ToByte(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToByte(CultureInfo.InvariantCulture)); - return; - case TypeCode.UInt32: - if (nullable) - WriteValue((uint?)convertible.ToUInt32(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToUInt32(CultureInfo.InvariantCulture)); - return; - case TypeCode.Int64: - if (nullable) - WriteValue((long?)convertible.ToInt64(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToInt64(CultureInfo.InvariantCulture)); - return; - case TypeCode.UInt64: - if (nullable) - WriteValue((ulong?)convertible.ToUInt64(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToUInt64(CultureInfo.InvariantCulture)); - return; - case TypeCode.Single: - if (nullable) - WriteValue((float?)convertible.ToSingle(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToSingle(CultureInfo.InvariantCulture)); - return; - case TypeCode.Double: - if (nullable) - WriteValue((double?)convertible.ToDouble(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToDouble(CultureInfo.InvariantCulture)); - return; - case TypeCode.DateTime: - if (nullable) - WriteValue((DateTime?)convertible.ToDateTime(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToDateTime(CultureInfo.InvariantCulture)); - return; - case TypeCode.Decimal: - if (nullable) - WriteValue((decimal?)convertible.ToDecimal(CultureInfo.InvariantCulture)); - else - WriteValue(convertible.ToDecimal(CultureInfo.InvariantCulture)); - return; -#if !(NETFX_CORE || PORTABLE) - case TypeCode.DBNull: - WriteNull(); - return; -#endif - } - } -#if !NET20 - else if (value is DateTimeOffset) - { - if (nullable) - WriteValue((DateTimeOffset?)value); - else - WriteValue((DateTimeOffset)value); - return; - } -#endif - else if (value is byte[]) - { - WriteValue((byte[])value); - return; - } - else if (value is Guid) - { - if (nullable) - WriteValue((Guid?)value); - else - WriteValue((Guid)value); - return; - } - else if (value is Uri) - { - WriteValue((Uri)value); - return; - } - else if (value is TimeSpan) - { - if (nullable) - WriteValue((TimeSpan?)value); - else - WriteValue((TimeSpan)value); - return; - } -#if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) - else if (value is BigInteger) - { - if (nullable) - WriteValue((BigInteger?)value); - else - WriteValue((BigInteger)value); - return; - } -#endif - - throw JsonWriterException.Create(this, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); + else + WriteValue(this, ConvertUtils.GetTypeCode(value), value); } #endregion @@ -1469,5 +1310,156 @@ namespace Newtonsoft.Json if (_currentState != State.Closed) Close(); } + + internal static void WriteValue(JsonWriter writer, PrimitiveTypeCode typeCode, object value) + { + switch (typeCode) + { + case PrimitiveTypeCode.Char: + writer.WriteValue((char)value); + break; + case PrimitiveTypeCode.CharNullable: + writer.WriteValue((value == null) ? (char?)null : (char)value); + break; + case PrimitiveTypeCode.Boolean: + writer.WriteValue((bool)value); + break; + case PrimitiveTypeCode.BooleanNullable: + writer.WriteValue((value == null) ? (bool?)null : (bool)value); + break; + case PrimitiveTypeCode.SByte: + writer.WriteValue((sbyte)value); + break; + case PrimitiveTypeCode.SByteNullable: + writer.WriteValue((value == null) ? (sbyte?)null : (sbyte)value); + break; + case PrimitiveTypeCode.Int16: + writer.WriteValue((short)value); + break; + case PrimitiveTypeCode.Int16Nullable: + writer.WriteValue((value == null) ? (short?)null : (short)value); + break; + case PrimitiveTypeCode.UInt16: + writer.WriteValue((ushort)value); + break; + case PrimitiveTypeCode.UInt16Nullable: + writer.WriteValue((value == null) ? (ushort?)null : (ushort)value); + break; + case PrimitiveTypeCode.Int32: + writer.WriteValue((int)value); + break; + case PrimitiveTypeCode.Int32Nullable: + writer.WriteValue((value == null) ? (int?)null : (int)value); + break; + case PrimitiveTypeCode.Byte: + writer.WriteValue((byte)value); + break; + case PrimitiveTypeCode.ByteNullable: + writer.WriteValue((value == null) ? (byte?)null : (byte)value); + break; + case PrimitiveTypeCode.UInt32: + writer.WriteValue((uint)value); + break; + case PrimitiveTypeCode.UInt32Nullable: + writer.WriteValue((value == null) ? (uint?)null : (uint)value); + break; + case PrimitiveTypeCode.Int64: + writer.WriteValue((long)value); + break; + case PrimitiveTypeCode.Int64Nullable: + writer.WriteValue((value == null) ? (long?)null : (long)value); + break; + case PrimitiveTypeCode.UInt64: + writer.WriteValue((ulong)value); + break; + case PrimitiveTypeCode.UInt64Nullable: + writer.WriteValue((value == null) ? (ulong?)null : (ulong)value); + break; + case PrimitiveTypeCode.Single: + writer.WriteValue((float)value); + break; + case PrimitiveTypeCode.SingleNullable: + writer.WriteValue((value == null) ? (float?)null : (float)value); + break; + case PrimitiveTypeCode.Double: + writer.WriteValue((double)value); + break; + case PrimitiveTypeCode.DoubleNullable: + writer.WriteValue((value == null) ? (double?)null : (double)value); + break; + case PrimitiveTypeCode.DateTime: + writer.WriteValue((DateTime)value); + break; + case PrimitiveTypeCode.DateTimeNullable: + writer.WriteValue((value == null) ? (DateTime?)null : (DateTime)value); + break; +#if !NET20 + case PrimitiveTypeCode.DateTimeOffset: + writer.WriteValue((DateTimeOffset)value); + break; + case PrimitiveTypeCode.DateTimeOffsetNullable: + writer.WriteValue((value == null) ? (DateTimeOffset?)null : (DateTimeOffset)value); + break; +#endif + case PrimitiveTypeCode.Decimal: + writer.WriteValue((decimal)value); + break; + case PrimitiveTypeCode.DecimalNullable: + writer.WriteValue((value == null) ? (decimal?)null : (decimal)value); + break; + case PrimitiveTypeCode.Guid: + writer.WriteValue((Guid)value); + break; + case PrimitiveTypeCode.GuidNullable: + writer.WriteValue((value == null) ? (Guid?)null : (Guid)value); + break; + case PrimitiveTypeCode.TimeSpan: + writer.WriteValue((TimeSpan)value); + break; + case PrimitiveTypeCode.TimeSpanNullable: + writer.WriteValue((value == null) ? (TimeSpan?)null : (TimeSpan)value); + break; +#if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) + case PrimitiveTypeCode.BigInteger: + writer.WriteValue((BigInteger)value); + break; + case PrimitiveTypeCode.BigIntegerNullable: + writer.WriteValue((value == null) ? (BigInteger?)null : (BigInteger)value); + break; +#endif + case PrimitiveTypeCode.Uri: + writer.WriteValue((Uri)value); + break; + case PrimitiveTypeCode.String: + writer.WriteValue((string)value); + break; + case PrimitiveTypeCode.Bytes: + writer.WriteValue((byte[])value); + break; +#if !(PORTABLE || NETFX_CORE) + case PrimitiveTypeCode.DBNull: + writer.WriteNull(); + break; +#endif + default: +#if !(PORTABLE || NETFX_CORE) + if (value is IConvertible) + { + // the value is a non-standard IConvertible + // convert to the underlying value and retry + IConvertible convertable = (IConvertible)value; + TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable); + object convertedValue = convertable.ToType(typeInformation.Type, CultureInfo.InvariantCulture); + + WriteValue(writer, typeInformation.TypeCode, convertedValue); + } + else +#endif + { + throw JsonWriterException.Create(writer, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); + } + break; + } + } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index a4649492..5dee3ce6 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -1636,126 +1636,91 @@ namespace Newtonsoft.Json.Linq private object ToObject(Type objectType, bool isNullable) { - TypeCode typeCode = ConvertUtils.GetTypeCode(objectType); + PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType); switch (typeCode) { - case TypeCode.Object: - if (!isNullable && ReflectionUtils.IsNullableType(objectType)) - return ToObject(Nullable.GetUnderlyingType(objectType), true); - - // fall back to standard JsonSerializer - break; - case TypeCode.Boolean: - if (isNullable) - return (bool?) this; - + case PrimitiveTypeCode.BooleanNullable: + return (bool?) this; + case PrimitiveTypeCode.Boolean: return (bool) this; - case TypeCode.Char: - if (isNullable) - return (char?) this; - + case PrimitiveTypeCode.CharNullable: + return (char?) this; + case PrimitiveTypeCode.Char: return (char) this; - case TypeCode.SByte: - if (isNullable) - return (sbyte?) this; - + case PrimitiveTypeCode.SByte: + return (sbyte?) this; + case PrimitiveTypeCode.SByteNullable: return (sbyte) this; - case TypeCode.Byte: - if (isNullable) - return (byte?) this; - + case PrimitiveTypeCode.ByteNullable: + return (byte?) this; + case PrimitiveTypeCode.Byte: return (byte) this; - case TypeCode.Int16: - if (isNullable) - return (short?) this; - + case PrimitiveTypeCode.Int16Nullable: + return (short?) this; + case PrimitiveTypeCode.Int16: return (short) this; - case TypeCode.UInt16: - if (isNullable) - return (ushort?) this; - + case PrimitiveTypeCode.UInt16Nullable: + return (ushort?) this; + case PrimitiveTypeCode.UInt16: return (ushort) this; - case TypeCode.Int32: - if (isNullable) - return (int?) this; - + case PrimitiveTypeCode.Int32Nullable: + return (int?) this; + case PrimitiveTypeCode.Int32: return (int) this; - case TypeCode.UInt32: - if (isNullable) - return (uint?) this; - + case PrimitiveTypeCode.UInt32Nullable: + return (uint?) this; + case PrimitiveTypeCode.UInt32: return (uint) this; - case TypeCode.Int64: - if (isNullable) - return (long?) this; - + case PrimitiveTypeCode.Int64Nullable: + return (long?) this; + case PrimitiveTypeCode.Int64: return (long) this; - case TypeCode.UInt64: - if (isNullable) - return (ulong?) this; - + case PrimitiveTypeCode.UInt64Nullable: + return (ulong?) this; + case PrimitiveTypeCode.UInt64: return (ulong) this; - case TypeCode.Single: - if (isNullable) - return (float?) this; - + case PrimitiveTypeCode.SingleNullable: + return (float?) this; + case PrimitiveTypeCode.Single: return (float) this; - case TypeCode.Double: - if (isNullable) - return (double?) this; - + case PrimitiveTypeCode.DoubleNullable: + return (double?) this; + case PrimitiveTypeCode.Double: return (double) this; - case TypeCode.Decimal: - if (isNullable) - return (decimal?) this; - + case PrimitiveTypeCode.DecimalNullable: + return (decimal?) this; + case PrimitiveTypeCode.Decimal: return (decimal) this; - case TypeCode.DateTime: - if (isNullable) - return (DateTime?) this; - + case PrimitiveTypeCode.DateTimeNullable: + return (DateTime?) this; + case PrimitiveTypeCode.DateTime: return (DateTime) this; - case TypeCode.String: - return (string) this; - } - #if !NET20 - if (objectType == typeof (DateTimeOffset)) - { - if (isNullable) + case PrimitiveTypeCode.DateTimeOffsetNullable: return (DateTimeOffset?) this; - - return (DateTimeOffset) this; - } + case PrimitiveTypeCode.DateTimeOffset: + return (DateTimeOffset) this; #endif - if (objectType == typeof (Guid)) - { - if (isNullable) + case PrimitiveTypeCode.String: + return (string) this; + case PrimitiveTypeCode.GuidNullable: return (Guid?) this; - - return (Guid) this; - } - if (objectType == typeof (Uri)) - { - return (Uri) this; - } - if (objectType == typeof (TimeSpan)) - { - if (isNullable) - return (TimeSpan?) this; - - return (TimeSpan) this; - } + case PrimitiveTypeCode.Guid: + return (Guid) this; + case PrimitiveTypeCode.Uri: + return (Uri) this; + case PrimitiveTypeCode.TimeSpanNullable: + return (TimeSpan?)this; + case PrimitiveTypeCode.TimeSpan: + return (TimeSpan)this; #if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) - if (objectType == typeof(BigInteger)) - { - if (isNullable) + case PrimitiveTypeCode.BigIntegerNullable: return (BigInteger?)this; - - return (BigInteger)this; - } + case PrimitiveTypeCode.BigInteger: + return (BigInteger)this; #endif + } return ToObject(objectType, new JsonSerializer()); } diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs index 65202610..7c9da1b7 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs @@ -30,9 +30,6 @@ using System.Collections.Generic; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Serialization; -#if NETFX_CORE -using IConvertible = Newtonsoft.Json.Utilities.Convertible; -#endif #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -321,8 +318,10 @@ namespace Newtonsoft.Json.Schema if (keyType != null) { + JsonContract keyContract = ContractResolver.ResolveContract(keyType); + // can be converted to a string - if (ConvertUtils.IsConvertible(keyType)) + if (keyContract.ContractType == JsonContractType.Primitive) { CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false); } @@ -421,38 +420,44 @@ namespace Newtonsoft.Json.Schema type = Nullable.GetUnderlyingType(type); } - TypeCode typeCode = ConvertUtils.GetTypeCode(type); + PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(type); switch (typeCode) { - case TypeCode.Empty: - case TypeCode.Object: + case PrimitiveTypeCode.Empty: + case PrimitiveTypeCode.Object: return schemaType | JsonSchemaType.String; #if !(NETFX_CORE || PORTABLE) - case TypeCode.DBNull: + case PrimitiveTypeCode.DBNull: return schemaType | JsonSchemaType.Null; #endif - case TypeCode.Boolean: + case PrimitiveTypeCode.Boolean: return schemaType | JsonSchemaType.Boolean; - case TypeCode.Char: + case PrimitiveTypeCode.Char: return schemaType | JsonSchemaType.String; - case TypeCode.SByte: - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: + case PrimitiveTypeCode.SByte: + case PrimitiveTypeCode.Byte: + case PrimitiveTypeCode.Int16: + case PrimitiveTypeCode.UInt16: + case PrimitiveTypeCode.Int32: + case PrimitiveTypeCode.UInt32: + case PrimitiveTypeCode.Int64: + case PrimitiveTypeCode.UInt64: + case PrimitiveTypeCode.BigInteger: return schemaType | JsonSchemaType.Integer; - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: + case PrimitiveTypeCode.Single: + case PrimitiveTypeCode.Double: + case PrimitiveTypeCode.Decimal: return schemaType | JsonSchemaType.Float; // convert to string? - case TypeCode.DateTime: + case PrimitiveTypeCode.DateTime: + case PrimitiveTypeCode.DateTimeOffset: return schemaType | JsonSchemaType.String; - case TypeCode.String: + case PrimitiveTypeCode.String: + case PrimitiveTypeCode.Uri: + case PrimitiveTypeCode.Guid: + case PrimitiveTypeCode.TimeSpan: + case PrimitiveTypeCode.Bytes: return schemaType | JsonSchemaType.String; default: throw new JsonException("Unexpected type code '{0}' for type '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeCode, type)); diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index fd8a1df3..78dfeae6 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -781,7 +781,7 @@ namespace Newtonsoft.Json.Serialization { Type t = ReflectionUtils.EnsureNotNullableType(objectType); - if (JsonConvert.IsJsonPrimitiveType(t)) + if (JsonConvert.IsJsonPrimitiveType(objectType)) return CreatePrimitiveContract(objectType); if (JsonTypeReflector.GetJsonObjectAttribute(t) != null) diff --git a/Src/Newtonsoft.Json/Serialization/JsonContract.cs b/Src/Newtonsoft.Json/Serialization/JsonContract.cs index bdf91c15..dccf6667 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonContract.cs @@ -28,9 +28,6 @@ using System.Collections.Generic; using System.Reflection; using System.Runtime.Serialization; using Newtonsoft.Json.Utilities; -#if NETFX_CORE -using IConvertible = Newtonsoft.Json.Utilities.Convertible; -#endif namespace Newtonsoft.Json.Serialization { diff --git a/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs b/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs index 23bdbc9d..6fccf30e 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs @@ -24,8 +24,8 @@ #endregion using System; -using System.Collections.Generic; #if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) +using System.Globalization; using System.Numerics; #endif using Newtonsoft.Json.Utilities; @@ -37,57 +37,6 @@ namespace Newtonsoft.Json.Serialization /// public class JsonPrimitiveContract : JsonContract { - private static readonly Dictionary TypeCodeMap = - new Dictionary - { - { typeof(char), PrimitiveTypeCode.Char }, - { typeof(char?), PrimitiveTypeCode.CharNullable }, - { typeof(bool), PrimitiveTypeCode.Boolean }, - { typeof(bool?), PrimitiveTypeCode.BooleanNullable }, - { typeof(sbyte), PrimitiveTypeCode.SByte }, - { typeof(sbyte?), PrimitiveTypeCode.SByteNullable }, - { typeof(short), PrimitiveTypeCode.Int16 }, - { typeof(short?), PrimitiveTypeCode.Int16Nullable }, - { typeof(ushort), PrimitiveTypeCode.UInt16 }, - { typeof(ushort?), PrimitiveTypeCode.UInt16Nullable }, - { typeof(int), PrimitiveTypeCode.Int32 }, - { typeof(int?), PrimitiveTypeCode.Int32Nullable }, - { typeof(byte), PrimitiveTypeCode.Byte }, - { typeof(byte?), PrimitiveTypeCode.ByteNullable }, - { typeof(uint), PrimitiveTypeCode.UInt32 }, - { typeof(uint?), PrimitiveTypeCode.UInt32Nullable }, - { typeof(long), PrimitiveTypeCode.Int64 }, - { typeof(long?), PrimitiveTypeCode.Int64Nullable }, - { typeof(ulong), PrimitiveTypeCode.UInt64 }, - { typeof(ulong?), PrimitiveTypeCode.UInt64Nullable }, - { typeof(float), PrimitiveTypeCode.Single }, - { typeof(float?), PrimitiveTypeCode.SingleNullable }, - { typeof(double), PrimitiveTypeCode.Double }, - { typeof(double?), PrimitiveTypeCode.DoubleNullable }, - { typeof(DateTime), PrimitiveTypeCode.DateTime }, - { typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable }, -#if !NET20 - { typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset }, - { typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable }, -#endif - { typeof(decimal), PrimitiveTypeCode.Decimal }, - { typeof(decimal?), PrimitiveTypeCode.DecimalNullable }, - { typeof(Guid), PrimitiveTypeCode.Guid }, - { typeof(Guid?), PrimitiveTypeCode.GuidNullable }, - { typeof(TimeSpan), PrimitiveTypeCode.TimeSpan }, - { typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable }, -#if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) - { typeof(BigInteger), PrimitiveTypeCode.BigInteger }, - { typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable }, -#endif - { typeof(Uri), PrimitiveTypeCode.Uri }, - { typeof(string), PrimitiveTypeCode.String }, - { typeof(byte[]), PrimitiveTypeCode.Bytes }, -#if !(PORTABLE || NETFX_CORE) - { typeof(DBNull), PrimitiveTypeCode.DBNull } -#endif - }; - internal PrimitiveTypeCode TypeCode { get; set; } /// @@ -99,256 +48,7 @@ namespace Newtonsoft.Json.Serialization { ContractType = JsonContractType.Primitive; - // get the underlying enum value - Type t; - if (ReflectionUtils.IsNullableType(underlyingType)) - t = Nullable.GetUnderlyingType(underlyingType).IsEnum() ? ReflectionUtils.MakeGenericType(typeof(Nullable<>), Enum.GetUnderlyingType(Nullable.GetUnderlyingType(underlyingType))) : underlyingType; - else - t = underlyingType.IsEnum() ? Enum.GetUnderlyingType(underlyingType) : underlyingType; - - PrimitiveTypeCode typeCode; - TypeCodeMap.TryGetValue(t, out typeCode); - TypeCode = typeCode; + TypeCode = ConvertUtils.GetTypeCode(underlyingType); } - - internal void WriteValue(JsonWriter writer, object value) - { - switch (TypeCode) - { - case PrimitiveTypeCode.Char: - writer.WriteValue((char)value); - break; - case PrimitiveTypeCode.CharNullable: - if (value != null) - writer.WriteValue((char)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Boolean: - writer.WriteValue((bool)value); - break; - case PrimitiveTypeCode.BooleanNullable: - if (value != null) - writer.WriteValue((bool)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.SByte: - writer.WriteValue((sbyte)value); - break; - case PrimitiveTypeCode.SByteNullable: - if (value != null) - writer.WriteValue((sbyte)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Int16: - writer.WriteValue((short)value); - break; - case PrimitiveTypeCode.Int16Nullable: - if (value != null) - writer.WriteValue((short)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.UInt16: - writer.WriteValue((ushort)value); - break; - case PrimitiveTypeCode.UInt16Nullable: - if (value != null) - writer.WriteValue((ushort)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Int32: - writer.WriteValue((int)value); - break; - case PrimitiveTypeCode.Int32Nullable: - if (value != null) - writer.WriteValue((int)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Byte: - writer.WriteValue((byte)value); - break; - case PrimitiveTypeCode.ByteNullable: - if (value != null) - writer.WriteValue((byte)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.UInt32: - writer.WriteValue((uint)value); - break; - case PrimitiveTypeCode.UInt32Nullable: - if (value != null) - writer.WriteValue((uint)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Int64: - writer.WriteValue((long)value); - break; - case PrimitiveTypeCode.Int64Nullable: - if (value != null) - writer.WriteValue((long)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.UInt64: - writer.WriteValue((ulong)value); - break; - case PrimitiveTypeCode.UInt64Nullable: - if (value != null) - writer.WriteValue((ulong)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Single: - writer.WriteValue((float)value); - break; - case PrimitiveTypeCode.SingleNullable: - // use nullable WriteValue to handle NaN, Infinity with FloatFormatHandling - if (value != null) - writer.WriteValue((float?)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Double: - writer.WriteValue((double)value); - break; - case PrimitiveTypeCode.DoubleNullable: - // use nullable WriteValue to handle NaN, Infinity with FloatFormatHandling - if (value != null) - writer.WriteValue((double?)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.DateTime: - writer.WriteValue((DateTime)value); - break; - case PrimitiveTypeCode.DateTimeNullable: - if (value != null) - writer.WriteValue((DateTime)value); - else - writer.WriteNull(); - break; -#if !NET20 - case PrimitiveTypeCode.DateTimeOffset: - writer.WriteValue((DateTimeOffset)value); - break; - case PrimitiveTypeCode.DateTimeOffsetNullable: - if (value != null) - writer.WriteValue((DateTimeOffset)value); - else - writer.WriteNull(); - break; -#endif - case PrimitiveTypeCode.Decimal: - writer.WriteValue((decimal)value); - break; - case PrimitiveTypeCode.DecimalNullable: - if (value != null) - writer.WriteValue((decimal)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.Guid: - writer.WriteValue((Guid)value); - break; - case PrimitiveTypeCode.GuidNullable: - if (value != null) - writer.WriteValue((Guid)value); - else - writer.WriteNull(); - break; - case PrimitiveTypeCode.TimeSpan: - writer.WriteValue((TimeSpan)value); - break; - case PrimitiveTypeCode.TimeSpanNullable: - if (value != null) - writer.WriteValue((TimeSpan)value); - else - writer.WriteNull(); - break; -#if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) - case PrimitiveTypeCode.BigInteger: - writer.WriteValue((BigInteger)value); - break; - case PrimitiveTypeCode.BigIntegerNullable: - if (value != null) - writer.WriteValue((BigInteger)value); - else - writer.WriteNull(); - break; -#endif - case PrimitiveTypeCode.Uri: - writer.WriteValue((Uri)value); - break; - case PrimitiveTypeCode.String: - writer.WriteValue((string)value); - break; - case PrimitiveTypeCode.Bytes: - writer.WriteValue((byte[])value); - break; -#if !(PORTABLE || NETFX_CORE) - case PrimitiveTypeCode.DBNull: - writer.WriteNull(); - break; -#endif - default: - throw new ArgumentOutOfRangeException("Could not write type: " + UnderlyingType); - } - } - } - - internal enum PrimitiveTypeCode - { - Unknown, - Char, - CharNullable, - Boolean, - BooleanNullable, - SByte, - SByteNullable, - Int16, - Int16Nullable, - UInt16, - UInt16Nullable, - Int32, - Int32Nullable, - Byte, - ByteNullable, - UInt32, - UInt32Nullable, - Int64, - Int64Nullable, - UInt64, - UInt64Nullable, - Single, - SingleNullable, - Double, - DoubleNullable, - DateTime, - DateTimeNullable, -#if !NET20 - DateTimeOffset, - DateTimeOffsetNullable, -#endif - Decimal, - DecimalNullable, - Guid, - GuidNullable, - TimeSpan, - TimeSpanNullable, -#if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) - BigInteger, - BigIntegerNullable, -#endif - Uri, - String, - Bytes, - DBNull } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index bfc9aeb3..20346993 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -693,11 +693,13 @@ To fix this error either change the JSON to a {1} or change the deserialized typ if (contract.IsConvertable) { + JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract; + if (contract.NonNullableUnderlyingType.IsEnum()) { if (value is string) return Enum.Parse(contract.NonNullableUnderlyingType, value.ToString(), true); - else if (ConvertUtils.IsInteger(value)) + else if (ConvertUtils.IsInteger(primitiveContract.TypeCode)) return Enum.ToObject(contract.NonNullableUnderlyingType, value); } @@ -706,6 +708,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ return ConvertUtils.FromBigInteger((BigInteger)value, targetType); #endif + // this won't work when converting to a custom IConvertible return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture); } @@ -966,6 +969,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ contract.ItemContract = GetContractSafe(contract.DictionaryValueType); JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); + PrimitiveTypeCode keyTypeCode = (contract.KeyContract is JsonPrimitiveContract) ? ((JsonPrimitiveContract)contract.KeyContract).TypeCode : PrimitiveTypeCode.Empty; bool finished = false; do @@ -979,11 +983,13 @@ To fix this error either change the JSON to a {1} or change the deserialized typ try { // this is for correctly reading ISO and MS formatted dictionary keys - if (contract.DictionaryKeyType == typeof(DateTime) && JsonConvert.TryParseDateTime(keyValue.ToString(), DateParseHandling.DateTime, reader.DateTimeZoneHandling, out keyValue)) + if ((keyTypeCode == PrimitiveTypeCode.DateTime || keyTypeCode == PrimitiveTypeCode.DateTimeNullable) + && JsonConvert.TryParseDateTime(keyValue.ToString(), DateParseHandling.DateTime, reader.DateTimeZoneHandling, out keyValue)) { } #if !NET20 - else if (contract.DictionaryKeyType == typeof(DateTimeOffset) && JsonConvert.TryParseDateTime(keyValue.ToString(), DateParseHandling.DateTimeOffset, reader.DateTimeZoneHandling, out keyValue)) + else if ((keyTypeCode == PrimitiveTypeCode.DateTimeOffset || keyTypeCode == PrimitiveTypeCode.DateTimeOffsetNullable) + && JsonConvert.TryParseDateTime(keyValue.ToString(), DateParseHandling.DateTimeOffset, reader.DateTimeZoneHandling, out keyValue)) { } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 05b833f0..af5d6ffb 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -94,14 +94,14 @@ namespace Newtonsoft.Json.Serialization WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName(JsonTypeReflector.ValuePropertyName); - contract.WriteValue(writer, value); + JsonWriter.WriteValue(writer, contract.TypeCode, value); writer.WriteEndObject(); return; } } - contract.WriteValue(writer, value); + JsonWriter.WriteValue(writer, contract.TypeCode, value); } private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) @@ -827,12 +827,15 @@ To fix this error either change the environment to be fully trusted, change the if (contract.ItemContract == null) contract.ItemContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); + if (contract.KeyContract == null) + contract.KeyContract = Serializer.ContractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object)); + int initialDepth = writer.Top; foreach (DictionaryEntry entry in values) { bool escape; - string propertyName = GetPropertyName(writer, entry, out escape); + string propertyName = GetPropertyName(writer, entry, contract.KeyContract, out escape); propertyName = (contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(propertyName) @@ -874,32 +877,36 @@ To fix this error either change the environment to be fully trusted, change the OnSerialized(writer, contract, underlyingDictionary); } - private string GetPropertyName(JsonWriter writer, DictionaryEntry entry, out bool escape) + private string GetPropertyName(JsonWriter writer, DictionaryEntry entry, JsonContract contract, out bool escape) { object key = entry.Key; string propertyName; - if (key is DateTime) + JsonPrimitiveContract primitiveContract = contract as JsonPrimitiveContract; + if (primitiveContract != null) { - escape = false; - StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); - JsonConvert.WriteDateTimeString(sw, (DateTime)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); - return sw.ToString(); - } + if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable) + { + escape = false; + StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); + JsonConvert.WriteDateTimeString(sw, (DateTime)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); + return sw.ToString(); + } #if !NET20 - else if (key is DateTimeOffset) - { - escape = false; - StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); - JsonConvert.WriteDateTimeOffsetString(sw, (DateTimeOffset)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); - return sw.ToString(); - } + else if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffset || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffsetNullable) + { + escape = false; + StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); + JsonConvert.WriteDateTimeOffsetString(sw, (DateTimeOffset)key, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); + return sw.ToString(); + } #endif - else if (ConvertUtils.IsConvertible(key)) - { - escape = true; - return Convert.ToString(key, CultureInfo.InvariantCulture); + else + { + escape = true; + return Convert.ToString(key, CultureInfo.InvariantCulture); + } } else if (TryConvertToString(key, key.GetType(), out propertyName)) { diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index 55c539e1..f7d6f903 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Collections.Generic; using System.Globalization; using System.ComponentModel; #if !(NET20 || NET35 || SILVERLIGHT || PORTABLE) @@ -38,181 +39,176 @@ using Newtonsoft.Json.Utilities.LinqBridge; #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) using System.Data.SqlTypes; #endif -#if NETFX_CORE || PORTABLE -using IConvertible = Newtonsoft.Json.Utilities.Convertible; -#endif namespace Newtonsoft.Json.Utilities { -#if NETFX_CORE || PORTABLE - internal class Convertible + internal enum PrimitiveTypeCode { - private object _underlyingValue; - - public Convertible(object o) - { - _underlyingValue = o; - } - - public TypeCode GetTypeCode() - { - return ConvertUtils.GetTypeCode(_underlyingValue); - } - - public bool ToBoolean(IFormatProvider provider) - { - return Convert.ToBoolean(_underlyingValue, provider); - } - public byte ToByte(IFormatProvider provider) - { - return Convert.ToByte(_underlyingValue, provider); - } - public char ToChar(IFormatProvider provider) - { - return Convert.ToChar(_underlyingValue, provider); - } - public DateTime ToDateTime(IFormatProvider provider) - { - return Convert.ToDateTime(_underlyingValue, provider); - } - public decimal ToDecimal(IFormatProvider provider) - { - return Convert.ToDecimal(_underlyingValue, provider); - } - public double ToDouble(IFormatProvider provider) - { - return Convert.ToDouble(_underlyingValue, provider); - } - public short ToInt16(IFormatProvider provider) - { - return Convert.ToInt16(_underlyingValue, provider); - } - public int ToInt32(IFormatProvider provider) - { - return Convert.ToInt32(_underlyingValue, provider); - } - public long ToInt64(IFormatProvider provider) - { - return Convert.ToInt64(_underlyingValue, provider); - } - public sbyte ToSByte(IFormatProvider provider) - { - return Convert.ToSByte(_underlyingValue, provider); - } - public float ToSingle(IFormatProvider provider) - { - return Convert.ToSingle(_underlyingValue, provider); - } - public string ToString(IFormatProvider provider) - { - return Convert.ToString(_underlyingValue, provider); - } - public object ToType(Type conversionType, IFormatProvider provider) - { - return Convert.ChangeType(_underlyingValue, conversionType, provider); - } - public ushort ToUInt16(IFormatProvider provider) - { - return Convert.ToUInt16(_underlyingValue, provider); - } - public uint ToUInt32(IFormatProvider provider) - { - return Convert.ToUInt32(_underlyingValue, provider); - } - public ulong ToUInt64(IFormatProvider provider) - { - return Convert.ToUInt64(_underlyingValue, provider); - } - } + Empty, + Object, + Char, + CharNullable, + Boolean, + BooleanNullable, + SByte, + SByteNullable, + Int16, + Int16Nullable, + UInt16, + UInt16Nullable, + Int32, + Int32Nullable, + Byte, + ByteNullable, + UInt32, + UInt32Nullable, + Int64, + Int64Nullable, + UInt64, + UInt64Nullable, + Single, + SingleNullable, + Double, + DoubleNullable, + DateTime, + DateTimeNullable, +#if !NET20 + DateTimeOffset, + DateTimeOffsetNullable, #endif + Decimal, + DecimalNullable, + Guid, + GuidNullable, + TimeSpan, + TimeSpanNullable, +#if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) + BigInteger, + BigIntegerNullable, +#endif + Uri, + String, + Bytes, + DBNull + } + + internal class TypeInformation + { + public Type Type { get; set; } + public PrimitiveTypeCode TypeCode { get; set; } + } internal static class ConvertUtils { - public static TypeCode GetTypeCode(this IConvertible convertible) - { -#if !(NETFX_CORE || PORTABLE) - return convertible.GetTypeCode(); -#else - return GetTypeCode((object)convertible); + private static readonly Dictionary TypeCodeMap = + new Dictionary + { + { typeof(char), PrimitiveTypeCode.Char }, + { typeof(char?), PrimitiveTypeCode.CharNullable }, + { typeof(bool), PrimitiveTypeCode.Boolean }, + { typeof(bool?), PrimitiveTypeCode.BooleanNullable }, + { typeof(sbyte), PrimitiveTypeCode.SByte }, + { typeof(sbyte?), PrimitiveTypeCode.SByteNullable }, + { typeof(short), PrimitiveTypeCode.Int16 }, + { typeof(short?), PrimitiveTypeCode.Int16Nullable }, + { typeof(ushort), PrimitiveTypeCode.UInt16 }, + { typeof(ushort?), PrimitiveTypeCode.UInt16Nullable }, + { typeof(int), PrimitiveTypeCode.Int32 }, + { typeof(int?), PrimitiveTypeCode.Int32Nullable }, + { typeof(byte), PrimitiveTypeCode.Byte }, + { typeof(byte?), PrimitiveTypeCode.ByteNullable }, + { typeof(uint), PrimitiveTypeCode.UInt32 }, + { typeof(uint?), PrimitiveTypeCode.UInt32Nullable }, + { typeof(long), PrimitiveTypeCode.Int64 }, + { typeof(long?), PrimitiveTypeCode.Int64Nullable }, + { typeof(ulong), PrimitiveTypeCode.UInt64 }, + { typeof(ulong?), PrimitiveTypeCode.UInt64Nullable }, + { typeof(float), PrimitiveTypeCode.Single }, + { typeof(float?), PrimitiveTypeCode.SingleNullable }, + { typeof(double), PrimitiveTypeCode.Double }, + { typeof(double?), PrimitiveTypeCode.DoubleNullable }, + { typeof(DateTime), PrimitiveTypeCode.DateTime }, + { typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable }, +#if !NET20 + { typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset }, + { typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable }, #endif - } - - public static TypeCode GetTypeCode(object o) - { -#if !(NETFX_CORE || PORTABLE) - return System.Convert.GetTypeCode(o); -#else - return GetTypeCode(o.GetType()); + { typeof(decimal), PrimitiveTypeCode.Decimal }, + { typeof(decimal?), PrimitiveTypeCode.DecimalNullable }, + { typeof(Guid), PrimitiveTypeCode.Guid }, + { typeof(Guid?), PrimitiveTypeCode.GuidNullable }, + { typeof(TimeSpan), PrimitiveTypeCode.TimeSpan }, + { typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable }, +#if !(PORTABLE || NET35 || NET20 || WINDOWS_PHONE || SILVERLIGHT) + { typeof(BigInteger), PrimitiveTypeCode.BigInteger }, + { typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable }, #endif - } + { typeof(Uri), PrimitiveTypeCode.Uri }, + { typeof(string), PrimitiveTypeCode.String }, + { typeof(byte[]), PrimitiveTypeCode.Bytes }, +#if !(PORTABLE || NETFX_CORE) + { typeof(DBNull), PrimitiveTypeCode.DBNull } +#endif + }; - public static TypeCode GetTypeCode(Type t) + private static readonly List PrimitiveTypeCodes = new List + { + new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, + new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Object }, + new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.DBNull }, + new TypeInformation { Type = typeof(bool), TypeCode = PrimitiveTypeCode.Boolean }, + new TypeInformation { Type = typeof(char), TypeCode = PrimitiveTypeCode.Char }, + new TypeInformation { Type = typeof(sbyte), TypeCode = PrimitiveTypeCode.SByte }, + new TypeInformation { Type = typeof(byte), TypeCode = PrimitiveTypeCode.Byte }, + new TypeInformation { Type = typeof(short), TypeCode = PrimitiveTypeCode.Int16 }, + new TypeInformation { Type = typeof(ushort), TypeCode = PrimitiveTypeCode.UInt16 }, + new TypeInformation { Type = typeof(int), TypeCode = PrimitiveTypeCode.Int32 }, + new TypeInformation { Type = typeof(uint), TypeCode = PrimitiveTypeCode.UInt32 }, + new TypeInformation { Type = typeof(long), TypeCode = PrimitiveTypeCode.Int64 }, + new TypeInformation { Type = typeof(ulong), TypeCode = PrimitiveTypeCode.UInt64 }, + new TypeInformation { Type = typeof(float), TypeCode = PrimitiveTypeCode.Single }, + new TypeInformation { Type = typeof(double), TypeCode = PrimitiveTypeCode.Double }, + new TypeInformation { Type = typeof(decimal), TypeCode = PrimitiveTypeCode.Decimal }, + new TypeInformation { Type = typeof(DateTime), TypeCode = PrimitiveTypeCode.DateTime }, + new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, // no 17 in TypeCode for some reason + new TypeInformation { Type = typeof(string), TypeCode = PrimitiveTypeCode.String } + }; + + public static PrimitiveTypeCode GetTypeCode(Type t) { -#if !(NETFX_CORE || PORTABLE) - return Type.GetTypeCode(t); -#else - if (t == typeof(bool)) - return TypeCode.Boolean; - if (t == typeof(byte)) - return TypeCode.Byte; - if (t == typeof(char)) - return TypeCode.Char; - if (t == typeof(DateTime)) - return TypeCode.DateTime; - if (t == typeof(decimal)) - return TypeCode.Decimal; - if (t == typeof(double)) - return TypeCode.Double; - if (t == typeof(short)) - return TypeCode.Int16; - if (t == typeof(int)) - return TypeCode.Int32; - if (t == typeof(long)) - return TypeCode.Int64; - if (t == typeof(sbyte)) - return TypeCode.SByte; - if (t == typeof(float)) - return TypeCode.Single; - if (t == typeof(string)) - return TypeCode.String; - if (t == typeof(ushort)) - return TypeCode.UInt16; - if (t == typeof(uint)) - return TypeCode.UInt32; - if (t == typeof(ulong)) - return TypeCode.UInt64; + PrimitiveTypeCode typeCode; + if (TypeCodeMap.TryGetValue(t, out typeCode)) + return typeCode; + if (t.IsEnum()) return GetTypeCode(Enum.GetUnderlyingType(t)); - return TypeCode.Object; -#endif + // performance? + if (ReflectionUtils.IsNullableType(t)) + { + Type nonNullable = Nullable.GetUnderlyingType(t); + if (nonNullable.IsEnum()) + { + Type nullableUnderlyingType = ReflectionUtils.MakeGenericType(typeof (Nullable<>), Enum.GetUnderlyingType(nonNullable)); + return GetTypeCode(nullableUnderlyingType); + } + } + + return PrimitiveTypeCode.Object; } - public static IConvertible ToConvertible(object o) + public static PrimitiveTypeCode GetTypeCode(object o) { -#if !(NETFX_CORE || PORTABLE) - return o as IConvertible; -#else - if (!IsConvertible(o)) - return null; - - return new IConvertible(o); -#endif + return GetTypeCode(o.GetType()); } - public static bool IsConvertible(object o) +#if !(NETFX_CORE || PORTABLE) + public static TypeInformation GetTypeInformation(IConvertible convertable) { -#if !(NETFX_CORE || PORTABLE) - return o is IConvertible; -#else - if (o == null) - return false; - - return ( - o is bool || o is byte || o is char || o is DateTime || o is decimal || o is double || o is short || o is int || - o is long || o is sbyte || o is float || o is string || o is ushort || o is uint || o is ulong || o is Enum); -#endif + TypeInformation typeInformation = PrimitiveTypeCodes[(int) convertable.GetTypeCode()]; + return typeInformation; } +#endif public static bool IsConvertible(Type t) { @@ -328,10 +324,15 @@ namespace Newtonsoft.Json.Utilities return (float) i; if (targetType == typeof (ulong)) return (ulong) i; - if (IsConvertible(targetType)) - return System.Convert.ChangeType((long) i, targetType, CultureInfo.InvariantCulture); - throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType)); + try + { + return System.Convert.ChangeType((long)i, targetType, CultureInfo.InvariantCulture); + } + catch (Exception ex) + { + throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType), ex); + } } #endif @@ -357,7 +358,7 @@ namespace Newtonsoft.Json.Utilities return initialValue; // use Convert.ChangeType if both types are IConvertible - if (ConvertUtils.IsConvertible(initialValue) && ConvertUtils.IsConvertible(targetType)) + if (ConvertUtils.IsConvertible(initialValue.GetType()) && ConvertUtils.IsConvertible(targetType)) { if (targetType.IsEnum()) { @@ -550,14 +551,14 @@ namespace Newtonsoft.Json.Utilities { switch (GetTypeCode(value)) { - case TypeCode.SByte: - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: + case PrimitiveTypeCode.SByte: + case PrimitiveTypeCode.Byte: + case PrimitiveTypeCode.Int16: + case PrimitiveTypeCode.UInt16: + case PrimitiveTypeCode.Int32: + case PrimitiveTypeCode.UInt32: + case PrimitiveTypeCode.Int64: + case PrimitiveTypeCode.UInt64: return true; default: return false; diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index 8d39e71f..8893a3de 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -25,15 +25,13 @@ using System; using System.Collections.Generic; +using System.Numerics; using System.Reflection; using System.Collections; using System.Globalization; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Text; -#if NETFX_CORE -using IConvertible = Newtonsoft.Json.Utilities.Convertible; -#endif #if NETFX_CORE || PORTABLE using ICustomAttributeProvider = Newtonsoft.Json.Utilities.CustomAttributeProvider; #endif @@ -70,29 +68,6 @@ namespace Newtonsoft.Json.Utilities get { return _underlyingObject; } } } -#endif - -#if (NETFX_CORE || PORTABLE) - internal enum TypeCode - { - Empty, - Object, - String, - Char, - Boolean, - SByte, - Int16, - UInt16, - Int32, - Byte, - UInt32, - Int64, - UInt64, - Single, - Double, - DateTime, - Decimal - } [Flags] internal enum BindingFlags @@ -985,37 +960,35 @@ namespace Newtonsoft.Json.Utilities switch (ConvertUtils.GetTypeCode(type)) { - case TypeCode.Boolean: + case PrimitiveTypeCode.Boolean: return false; - case TypeCode.Char: - case TypeCode.SByte: - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: + case PrimitiveTypeCode.Char: + case PrimitiveTypeCode.SByte: + case PrimitiveTypeCode.Byte: + case PrimitiveTypeCode.Int16: + case PrimitiveTypeCode.UInt16: + case PrimitiveTypeCode.Int32: + case PrimitiveTypeCode.UInt32: return 0; - case TypeCode.Int64: - case TypeCode.UInt64: + case PrimitiveTypeCode.Int64: + case PrimitiveTypeCode.UInt64: return 0L; - case TypeCode.Single: + case PrimitiveTypeCode.Single: return 0f; - case TypeCode.Double: + case PrimitiveTypeCode.Double: return 0.0; - case TypeCode.Decimal: + case PrimitiveTypeCode.Decimal: return 0m; - case TypeCode.DateTime: + case PrimitiveTypeCode.DateTime: return new DateTime(); + case PrimitiveTypeCode.BigInteger: + return new BigInteger(); + case PrimitiveTypeCode.Guid: + return new Guid(); + case PrimitiveTypeCode.DateTimeOffset: + return new DateTimeOffset(); } - if (type == typeof(Guid)) - return new Guid(); - -#if !NET20 - if (type == typeof(DateTimeOffset)) - return new DateTimeOffset(); -#endif - if (IsNullable(type)) return null;