-Added ReadAsDouble

This commit is contained in:
James Newton-King
2015-12-26 15:53:27 +13:00
parent 7f290b5a85
commit 3773eb5be7
11 changed files with 390 additions and 15 deletions
@@ -2771,6 +2771,35 @@ new Date()"));
Assert.AreEqual(JsonToken.EndConstructor, reader.TokenType);
}
[Test]
public void ReadAsDouble_Null()
{
JsonTextReader reader = new JsonTextReader(new StringReader("null"));
Assert.AreEqual(null, reader.ReadAsDouble());
}
[Test]
public void ReadAsDouble_Success()
{
JsonTextReader reader = new JsonTextReader(new StringReader("'12.34'"));
Assert.AreEqual(12.34d, reader.ReadAsDouble());
}
[Test]
public void ReadAsDouble_Failure()
{
JsonTextReader reader = new JsonTextReader(new StringReader("['Trump',1]"));
Assert.IsTrue(reader.Read());
ExceptionAssert.Throws<JsonReaderException>(
() => { reader.ReadAsDouble(); },
"Could not convert string to double: Trump. Path '[0]', line 1, position 8.");
Assert.AreEqual(1d, reader.ReadAsDouble());
Assert.IsTrue(reader.Read());
}
[Test]
public void ParseConstructorWithBadCharacter()
{
@@ -2905,7 +2934,7 @@ new Date()"));
ExceptionAssert.Throws<JsonReaderException>(() =>
{
reader.ReadAsBytes();
}, "Unexpected character encountered while parsing value: ,. Path '[1]', line 1, position 4.");
}, "Unexpected character encountered while parsing value: ,. Path '[1]', line 1, position 5.");
CollectionAssert.AreEquivalent(new byte[0], reader.ReadAsBytes());
Assert.IsTrue(reader.Read());
@@ -2967,10 +2996,11 @@ new Date()"));
Assert.IsTrue(reader.Read());
}
#if !NET20
[Test]
public void ReadValue_EmptyString_Position()
{
string json = @"['','','','','','']";
string json = @"['','','','','','','']";
JsonTextReader reader = new JsonTextReader(new StringReader(json));
@@ -2987,6 +3017,8 @@ new Date()"));
Assert.AreEqual("[4]", reader.Path);
reader.ReadAsBytes();
Assert.AreEqual("[5]", reader.Path);
reader.ReadAsDouble();
Assert.AreEqual("[6]", reader.Path);
Assert.IsNull(reader.ReadAsString());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -2997,6 +3029,7 @@ new Date()"));
Assert.IsNull(reader.ReadAsBytes());
Assert.AreEqual(JsonToken.None, reader.TokenType);
}
#endif
[Test]
public void ReadValueComments()
@@ -3783,7 +3816,6 @@ null//comment
var serverStartedEvent = new ManualResetEvent(false);
var clientReceivedEvent = new ManualResetEvent(false);
#region server
ThreadPool.QueueUserWorkItem(work =>
{
var server = new TcpListener(IPAddress.Parse("0.0.0.0"), port);
@@ -3802,7 +3834,6 @@ null//comment
clientReceivedEvent.WaitOne();
});
#endregion
serverStartedEvent.WaitOne();
@@ -3838,6 +3869,7 @@ null//comment
Console.WriteLine("Done");
}
#endif
[Test]
public void DisposeSupressesFinalization()
{
@@ -726,5 +726,201 @@ namespace Newtonsoft.Json.Tests.Linq
Assert.IsFalse(reader.Read());
Assert.AreEqual("[0]", reader.Path);
}
[Test]
public void ReadAsDouble_InvalidToken()
{
JArray a = new JArray
{
1, 2
};
JTokenReader reader = new JTokenReader(a);
ExceptionAssert.Throws<JsonReaderException>(
() => { reader.ReadAsDouble(); },
"Error reading double. Unexpected token: StartArray. Path ''.");
}
[Test]
public void ReadAsDateTime_InvalidToken()
{
JArray a = new JArray
{
1, 2
};
JTokenReader reader = new JTokenReader(a);
ExceptionAssert.Throws<JsonReaderException>(
() => { reader.ReadAsDateTime(); },
"Error reading date. Unexpected token: StartArray. Path ''.");
}
#if !NET20
[Test]
public void ReadAsDateTimeOffset_InvalidToken()
{
JArray a = new JArray
{
1, 2
};
JTokenReader reader = new JTokenReader(a);
ExceptionAssert.Throws<JsonReaderException>(
() => { reader.ReadAsDateTimeOffset(); },
"Error reading date. Unexpected token: StartArray. Path ''.");
}
[Test]
public void ReadAsDateTimeOffset_DateTime()
{
JValue v = new JValue(new DateTime(2001, 12, 12, 12, 12, 12, DateTimeKind.Utc));
JTokenReader reader = new JTokenReader(v);
Assert.AreEqual(new DateTimeOffset(2001, 12, 12, 12, 12, 12, TimeSpan.Zero), reader.ReadAsDateTimeOffset());
}
[Test]
public void ReadAsDateTimeOffset_String()
{
JValue v = new JValue("2012-01-24T03:50Z");
JTokenReader reader = new JTokenReader(v);
Assert.AreEqual(new DateTimeOffset(2012, 1, 24, 3, 50, 0, TimeSpan.Zero), reader.ReadAsDateTimeOffset());
}
[Test]
public void ReadAsDateTime_DateTimeOffset()
{
JValue v = new JValue(new DateTimeOffset(2012, 1, 24, 3, 50, 0, TimeSpan.Zero));
JTokenReader reader = new JTokenReader(v);
Assert.AreEqual(new DateTime(2012, 1, 24, 3, 50, 0, DateTimeKind.Utc), reader.ReadAsDateTime());
}
#endif
[Test]
public void ReadAsDateTime_String()
{
JValue v = new JValue("2012-01-24T03:50Z");
JTokenReader reader = new JTokenReader(v);
Assert.AreEqual(new DateTime(2012, 1, 24, 3, 50, 0, DateTimeKind.Utc), reader.ReadAsDateTime());
}
[Test]
public void ReadAsDouble_String_Success()
{
JValue s = JValue.CreateString("123.4");
JTokenReader reader = new JTokenReader(s);
Assert.AreEqual(123.4d, reader.ReadAsDouble());
}
[Test]
public void ReadAsDouble_Null_Success()
{
JValue n = JValue.CreateNull();
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual(null, reader.ReadAsDouble());
}
[Test]
public void ReadAsDouble_Integer_Success()
{
JValue n = new JValue(1);
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual(1d, reader.ReadAsDouble());
}
[Test]
public void ReadAsDateTime_Null_Success()
{
JValue n = JValue.CreateNull();
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual(null, reader.ReadAsDateTime());
}
#if !NET20
[Test]
public void ReadAsDateTimeOffset_Null_Success()
{
JValue n = JValue.CreateNull();
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual(null, reader.ReadAsDateTimeOffset());
}
#endif
[Test]
public void ReadAsString_Integer_Success()
{
JValue n = new JValue(1);
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual("1", reader.ReadAsString());
}
[Test]
public void ReadAsString_Guid_Success()
{
JValue n = new JValue(new Uri("http://www.test.com"));
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual("http://www.test.com", reader.ReadAsString());
}
[Test]
public void ReadAsBytes_Integer_Success()
{
JValue n = JValue.CreateNull();
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual(null, reader.ReadAsBytes());
}
[Test]
public void ReadAsBytes_Array()
{
JArray a = new JArray
{
1, 2
};
JTokenReader reader = new JTokenReader(a);
byte[] bytes = reader.ReadAsBytes();
Assert.AreEqual(2, bytes.Length);
Assert.AreEqual(1, bytes[0]);
Assert.AreEqual(2, bytes[1]);
}
[Test]
public void ReadAsBytes_Null()
{
JValue n = JValue.CreateNull();
JTokenReader reader = new JTokenReader(n);
Assert.AreEqual(null, reader.ReadAsBytes());
}
}
}
@@ -3716,9 +3716,9 @@ Path '', line 1, position 1.");
{
string json = @"[]";
ExceptionAssert.Throws<JsonSerializationException>(() => { JsonConvert.DeserializeObject<double>(json); }, @"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Double' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly.
To fix this error either change the JSON to a JSON primitive value (e.g. string, number, boolean, null) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.");
ExceptionAssert.Throws<JsonReaderException>(
() => { JsonConvert.DeserializeObject<double>(json); },
@"Unexpected character encountered while parsing value: [. Path '', line 1, position 1.");
}
#if !(NET35 || NET20 || PORTABLE40)
@@ -532,7 +532,7 @@ namespace Newtonsoft.Json.Tests.Serialization
public class ItemWithTypedPayload
{
public double Payload { get; set; }
public float Payload { get; set; }
}
[Test]
@@ -540,19 +540,19 @@ namespace Newtonsoft.Json.Tests.Serialization
{
ItemWithTypedPayload actual = JsonConvert.DeserializeObject<ItemWithTypedPayload>(@"{
""Payload"": {
""$type"": ""System.Double, mscorlib"",
""$type"": ""System.Single, mscorlib"",
""$value"": ""5""
}
}",
new JsonSerializerSettings());
Assert.AreEqual(5d, actual.Payload);
Assert.AreEqual(5f, actual.Payload);
ExceptionAssert.Throws<JsonSerializationException>(() =>
{
JsonConvert.DeserializeObject<ItemWithTypedPayload>(@"{
""Payload"": {
""$type"": ""System.Double, mscorlib"",
""$type"": ""System.Single, mscorlib"",
""$value"": ""5""
}
}",
@@ -560,7 +560,7 @@ namespace Newtonsoft.Json.Tests.Serialization
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore
});
}, @"Cannot deserialize the current JSON object (e.g. {""name"":""value""}) into type 'System.Double' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly.
}, @"Cannot deserialize the current JSON object (e.g. {""name"":""value""}) into type 'System.Single' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly.
To fix this error either change the JSON to a JSON primitive value (e.g. string, number, boolean, null) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'Payload.$type', line 3, position 12.");
}
+61
View File
@@ -484,6 +484,10 @@ namespace Newtonsoft.Json
{
s = ((IFormattable)Value).ToString(null, Culture);
}
else if (Value is Uri)
{
s = ((Uri)Value).OriginalString;
}
else
{
s = Value.ToString();
@@ -590,6 +594,56 @@ namespace Newtonsoft.Json
}
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public virtual double? ReadAsDouble()
{
JsonToken t = GetContentToken();
switch (t)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
if (!(Value is double))
{
SetToken(JsonToken.Float, Convert.ToDouble(Value, CultureInfo.InvariantCulture), false);
}
return (double) Value;
case JsonToken.String:
return ReadDoubleString((string) Value);
}
throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
internal double? ReadDoubleString(string s)
{
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, false);
return null;
}
double d;
if (double.TryParse(s, NumberStyles.Float, Culture, out d))
{
SetToken(JsonToken.Float, d, false);
return d;
}
else
{
SetToken(JsonToken.String, s, false);
throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
@@ -653,6 +707,13 @@ namespace Newtonsoft.Json
case JsonToken.EndArray:
return null;
case JsonToken.Date:
#if !NET20
if (Value is DateTimeOffset)
{
SetToken(JsonToken.Date, ((DateTimeOffset)Value).DateTime, false);
}
#endif
return (DateTime)Value;
case JsonToken.String:
string s = (string)Value;
+54 -2
View File
@@ -43,8 +43,9 @@ namespace Newtonsoft.Json
ReadAsDecimal,
ReadAsDateTime,
#if !NET20
ReadAsDateTimeOffset
ReadAsDateTimeOffset,
#endif
ReadAsDouble
}
/// <summary>
@@ -702,6 +703,8 @@ namespace Newtonsoft.Json
return ReadInt32String(_stringReference.ToString());
case ReadType.ReadAsDecimal:
return ReadDecimalString(_stringReference.ToString());
case ReadType.ReadAsDouble:
return ReadDoubleString(_stringReference.ToString());
default:
throw new ArgumentOutOfRangeException(nameof(readType));
}
@@ -765,8 +768,8 @@ namespace Newtonsoft.Json
// eat
break;
}
}
}
case State.Finished:
ReadFinished();
SetToken(JsonToken.None);
@@ -796,6 +799,15 @@ namespace Newtonsoft.Json
return (decimal?)ReadNumberValue(ReadType.ReadAsDecimal);
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Double}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Double}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override double? ReadAsDouble()
{
return (double?)ReadNumberValue(ReadType.ReadAsDouble);
}
private void HandleNull()
{
if (EnsureChars(1, true))
@@ -1733,6 +1745,46 @@ namespace Newtonsoft.Json
numberType = JsonToken.Float;
}
else if (readType == ReadType.ReadAsDouble)
{
if (singleDigit)
{
// digit char values start at 48
numberValue = (double)firstChar - 48;
}
else if (nonBase10)
{
string number = _stringReference.ToString();
try
{
// double.Parse doesn't support parsing hexadecimal values
long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8);
numberValue = Convert.ToDouble(integer);
}
catch (Exception ex)
{
throw JsonReaderException.Create(this, "Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, number), ex);
}
}
else
{
string number = _stringReference.ToString();
double value;
if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
numberValue = value;
}
else
{
throw JsonReaderException.Create(this, "Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
}
numberType = JsonToken.Float;
}
else
{
if (singleDigit)
@@ -429,6 +429,18 @@ namespace Newtonsoft.Json
return d;
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Double}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Double}"/>.</returns>
public override double? ReadAsDouble()
{
double? d = _reader.ReadAsDouble();
ValidateCurrentToken();
return d;
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
+9 -1
View File
@@ -225,7 +225,15 @@ namespace Newtonsoft.Json.Linq
SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
break;
case JTokenType.Uri:
SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
object v = ((JValue)token).Value;
if (v is Uri)
{
SetToken(JsonToken.String, ((Uri)v).OriginalString);
}
else
{
SetToken(JsonToken.String, SafeToString(v));
}
break;
case JTokenType.TimeSpan:
SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
@@ -347,6 +347,10 @@ namespace Newtonsoft.Json.Serialization
InternalReadType = ReadType.ReadAsDateTimeOffset;
}
#endif
else if (NonNullableUnderlyingType == typeof(double))
{
InternalReadType = ReadType.ReadAsDouble;
}
else
{
InternalReadType = ReadType.Read;
@@ -2210,6 +2210,9 @@ namespace Newtonsoft.Json.Serialization
case ReadType.ReadAsDecimal:
reader.ReadAsDecimal();
break;
case ReadType.ReadAsDouble:
reader.ReadAsDouble();
break;
case ReadType.ReadAsBytes:
reader.ReadAsBytes();
break;
@@ -64,6 +64,13 @@ namespace Newtonsoft.Json.Serialization
return value;
}
public override double? ReadAsDouble()
{
var value = _innerReader.ReadAsDouble();
_textWriter.WriteToken(_innerReader, false, false, true);
return value;
}
public override DateTime? ReadAsDateTime()
{
var value = _innerReader.ReadAsDateTime();