-Fixed reading NaN, Infinity, -Infinity with ReadAsDouble and ReadAsString
This commit is contained in:
@@ -61,6 +61,95 @@ namespace Newtonsoft.Json.Tests
|
||||
[TestFixture]
|
||||
public class JsonTextReaderTest : TestFixtureBase
|
||||
{
|
||||
[Test]
|
||||
public void Float_NaN_Read()
|
||||
{
|
||||
const string testJson = "{float: NaN}";
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(testJson));
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.IsTrue(reader.Read());
|
||||
|
||||
Assert.AreEqual(JsonToken.Float, reader.TokenType);
|
||||
Assert.AreEqual(double.NaN, reader.Value);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.IsFalse(reader.Read());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Float_NaN_ReadAsInt32()
|
||||
{
|
||||
const string testJson = "{float: NaN}";
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(testJson));
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.IsTrue(reader.Read());
|
||||
|
||||
ExceptionAssert.Throws<JsonReaderException>(() => reader.ReadAsInt32(), "Cannot read NaN value. Path 'float', line 1, position 11.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Float_NaNAndInifinity_ReadAsDouble()
|
||||
{
|
||||
const string testJson = @"[
|
||||
NaN,
|
||||
Infinity,
|
||||
-Infinity
|
||||
]"; ;
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(testJson));
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
|
||||
Assert.AreEqual(double.NaN, reader.ReadAsDouble());
|
||||
Assert.AreEqual(JsonToken.Float, reader.TokenType);
|
||||
Assert.AreEqual(double.NaN, reader.Value);
|
||||
|
||||
Assert.AreEqual(double.PositiveInfinity, reader.ReadAsDouble());
|
||||
Assert.AreEqual(JsonToken.Float, reader.TokenType);
|
||||
Assert.AreEqual(double.PositiveInfinity, reader.Value);
|
||||
|
||||
Assert.AreEqual(double.NegativeInfinity, reader.ReadAsDouble());
|
||||
Assert.AreEqual(JsonToken.Float, reader.TokenType);
|
||||
Assert.AreEqual(double.NegativeInfinity, reader.Value);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.IsFalse(reader.Read());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Float_NaNAndInifinity_ReadAsString()
|
||||
{
|
||||
const string testJson = @"[
|
||||
NaN,
|
||||
Infinity,
|
||||
-Infinity
|
||||
]"; ;
|
||||
|
||||
JsonTextReader reader = new JsonTextReader(new StringReader(testJson));
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
|
||||
Assert.AreEqual(JsonConvert.NaN, reader.ReadAsString());
|
||||
Assert.AreEqual(JsonToken.String, reader.TokenType);
|
||||
Assert.AreEqual(JsonConvert.NaN, reader.Value);
|
||||
|
||||
Assert.AreEqual(JsonConvert.PositiveInfinity, reader.ReadAsString());
|
||||
Assert.AreEqual(JsonToken.String, reader.TokenType);
|
||||
Assert.AreEqual(JsonConvert.PositiveInfinity, reader.Value);
|
||||
|
||||
Assert.AreEqual(JsonConvert.NegativeInfinity, reader.ReadAsString());
|
||||
Assert.AreEqual(JsonToken.String, reader.TokenType);
|
||||
Assert.AreEqual(JsonConvert.NegativeInfinity, reader.Value);
|
||||
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.IsFalse(reader.Read());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FloatParseHandling_ReadAsString()
|
||||
{
|
||||
@@ -486,7 +575,7 @@ third line", jsonTextReader.Value);
|
||||
Assert.IsTrue(reader.Read());
|
||||
Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
|
||||
|
||||
ExceptionAssert.Throws<JsonReaderException>(() => reader.Read(), "Cannot read NaN as a decimal.");
|
||||
ExceptionAssert.Throws<JsonReaderException>(() => reader.Read(), "Cannot read NaN value. Path '', line 1, position 4.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -598,6 +598,15 @@ namespace Newtonsoft.Json
|
||||
throw new ArgumentOutOfRangeException(nameof(readType));
|
||||
}
|
||||
case '-':
|
||||
if (EnsureChars(1, true) && _chars[_charPos + 1] == 'I')
|
||||
{
|
||||
return ParseNumberNegativeInfinity(readType);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseNumber(readType);
|
||||
return Value;
|
||||
}
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
@@ -630,6 +639,10 @@ namespace Newtonsoft.Json
|
||||
}
|
||||
SetToken(JsonToken.String, expected);
|
||||
return expected;
|
||||
case 'I':
|
||||
return ParseNumberPositiveInfinity(readType);
|
||||
case 'N':
|
||||
return ParseNumberNaN(readType);
|
||||
case 'n':
|
||||
HandleNull();
|
||||
return null;
|
||||
@@ -858,7 +871,20 @@ namespace Newtonsoft.Json
|
||||
case 'n':
|
||||
HandleNull();
|
||||
return null;
|
||||
case 'N':
|
||||
return ParseNumberNaN(readType);
|
||||
case 'I':
|
||||
return ParseNumberPositiveInfinity(readType);
|
||||
case '-':
|
||||
if (EnsureChars(1, true) && _chars[_charPos + 1] == 'I')
|
||||
{
|
||||
return ParseNumberNegativeInfinity(readType);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseNumber(readType);
|
||||
return Value;
|
||||
}
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
@@ -1567,15 +1593,15 @@ namespace Newtonsoft.Json
|
||||
}
|
||||
return true;
|
||||
case 'N':
|
||||
ParseNumberNaN();
|
||||
ParseNumberNaN(ReadType.Read);
|
||||
return true;
|
||||
case 'I':
|
||||
ParseNumberPositiveInfinity();
|
||||
ParseNumberPositiveInfinity(ReadType.Read);
|
||||
return true;
|
||||
case '-':
|
||||
if (EnsureChars(1, true) && _chars[_charPos + 1] == 'I')
|
||||
{
|
||||
ParseNumberNegativeInfinity();
|
||||
ParseNumberNegativeInfinity(ReadType.Read);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2293,55 +2319,79 @@ namespace Newtonsoft.Json
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseNumberNegativeInfinity()
|
||||
private object ParseNumberNegativeInfinity(ReadType readType)
|
||||
{
|
||||
if (MatchValueWithTrailingSeparator(JsonConvert.NegativeInfinity))
|
||||
{
|
||||
if (_floatParseHandling == FloatParseHandling.Decimal)
|
||||
switch (readType)
|
||||
{
|
||||
throw new JsonReaderException("Cannot read -Infinity as a decimal.");
|
||||
case ReadType.Read:
|
||||
case ReadType.ReadAsDouble:
|
||||
if (_floatParseHandling == FloatParseHandling.Double)
|
||||
{
|
||||
SetToken(JsonToken.Float, double.NegativeInfinity);
|
||||
return double.NegativeInfinity;
|
||||
}
|
||||
break;
|
||||
case ReadType.ReadAsString:
|
||||
SetToken(JsonToken.String, JsonConvert.NegativeInfinity);
|
||||
return JsonConvert.NegativeInfinity;
|
||||
}
|
||||
|
||||
SetToken(JsonToken.Float, double.NegativeInfinity);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Error parsing negative infinity value.");
|
||||
throw JsonReaderException.Create(this, "Cannot read -Infinity value.");
|
||||
}
|
||||
|
||||
throw JsonReaderException.Create(this, "Error parsing -Infinity value.");
|
||||
}
|
||||
|
||||
private void ParseNumberPositiveInfinity()
|
||||
private object ParseNumberPositiveInfinity(ReadType readType)
|
||||
{
|
||||
if (MatchValueWithTrailingSeparator(JsonConvert.PositiveInfinity))
|
||||
{
|
||||
if (_floatParseHandling == FloatParseHandling.Decimal)
|
||||
switch (readType)
|
||||
{
|
||||
throw new JsonReaderException("Cannot read Infinity as a decimal.");
|
||||
case ReadType.Read:
|
||||
case ReadType.ReadAsDouble:
|
||||
if (_floatParseHandling == FloatParseHandling.Double)
|
||||
{
|
||||
SetToken(JsonToken.Float, double.PositiveInfinity);
|
||||
return double.PositiveInfinity;
|
||||
}
|
||||
break;
|
||||
case ReadType.ReadAsString:
|
||||
SetToken(JsonToken.String, JsonConvert.PositiveInfinity);
|
||||
return JsonConvert.PositiveInfinity;
|
||||
}
|
||||
|
||||
SetToken(JsonToken.Float, double.PositiveInfinity);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Error parsing positive infinity value.");
|
||||
throw JsonReaderException.Create(this, "Cannot read Infinity value.");
|
||||
}
|
||||
|
||||
throw JsonReaderException.Create(this, "Error parsing Infinity value.");
|
||||
}
|
||||
|
||||
private void ParseNumberNaN()
|
||||
private object ParseNumberNaN(ReadType readType)
|
||||
{
|
||||
if (MatchValueWithTrailingSeparator(JsonConvert.NaN))
|
||||
{
|
||||
if (_floatParseHandling == FloatParseHandling.Decimal)
|
||||
switch (readType)
|
||||
{
|
||||
throw new JsonReaderException("Cannot read NaN as a decimal.");
|
||||
case ReadType.Read:
|
||||
case ReadType.ReadAsDouble:
|
||||
if (_floatParseHandling == FloatParseHandling.Double)
|
||||
{
|
||||
SetToken(JsonToken.Float, double.NaN);
|
||||
return double.NaN;
|
||||
}
|
||||
break;
|
||||
case ReadType.ReadAsString:
|
||||
SetToken(JsonToken.String, JsonConvert.NaN);
|
||||
return JsonConvert.NaN;
|
||||
}
|
||||
|
||||
SetToken(JsonToken.Float, double.NaN);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw JsonReaderException.Create(this, "Error parsing NaN value.");
|
||||
throw JsonReaderException.Create(this, "Cannot read NaN value.");
|
||||
}
|
||||
|
||||
throw JsonReaderException.Create(this, "Error parsing NaN value.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user