Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8013865
Json prototype (#1)
kasiabulat Jul 17, 2019
0f7df28
Json prototype - transformation API (#2)
kasiabulat Jul 19, 2019
6cd2efb
Json prototype (#1)
kasiabulat Jul 17, 2019
409e575
Json prototype - transformation API (#2)
kasiabulat Jul 19, 2019
25109c3
Merge branch 'master' of https://github.com/kasiabulat/corefx
kasiabulat Jul 29, 2019
9dcfc4b
JsonNumber implementation and tests (#3)
kasiabulat Jul 30, 2019
38af6d9
Merge remote-tracking branch 'upstream/master'
kasiabulat Jul 30, 2019
08f4734
all unimplemented classes and methods with accompanying tests removed
kasiabulat Jul 30, 2019
63ff329
First part of documentation added
kasiabulat Jul 30, 2019
0e0fb7c
documentation completed
kasiabulat Jul 31, 2019
47666ce
missing exceptions added
kasiabulat Jul 31, 2019
d856681
JsonElement changes removed
kasiabulat Jul 31, 2019
22e6558
part of the review comments included
kasiabulat Aug 1, 2019
04441f1
work on review comments
kasiabulat Aug 1, 2019
30c5dd0
code refactor
kasiabulat Aug 5, 2019
8f3e510
more decimal tests added using MemberData
kasiabulat Aug 5, 2019
c6ab148
more decimal tests added using MemberData
kasiabulat Aug 5, 2019
259590b
more test cases added
kasiabulat Aug 5, 2019
c4d6ef2
equals summary adjusted, equals tests added
kasiabulat Aug 5, 2019
01c230f
more Equals tests added, GetHashCode tests added, minor changes
kasiabulat Aug 6, 2019
392142a
scientifing notation support added, rational numbers tests fixes
kasiabulat Aug 6, 2019
310a5a6
rational overflow tests added
kasiabulat Aug 6, 2019
e03b803
ulong maxvalue tests added to rational types
kasiabulat Aug 6, 2019
95a9401
presision problems fixes
kasiabulat Aug 6, 2019
2bd6871
exception strings fixed
kasiabulat Aug 6, 2019
f0c4814
CI failing fixes (hopefully), review comments included
kasiabulat Aug 7, 2019
c22b36d
missing == tests added to achieve 100% branch coverage
kasiabulat Aug 7, 2019
7dfc891
review comments included
kasiabulat Aug 8, 2019
07746d8
Merge remote-tracking branch 'upstream/master' into kasiabulat/json-n…
kasiabulat Aug 8, 2019
d479fa7
Merge remote-tracking branch 'upstream/master' into kasiabulat/json-n…
kasiabulat Aug 8, 2019
ab1401a
trailing whitespaces fixes
kasiabulat Aug 8, 2019
217bade
equals comments added
kasiabulat Aug 8, 2019
40a6649
equals object refactored to call quals json number
kasiabulat Aug 8, 2019
af4aed3
Merge conflicts resolved
kasiabulat Aug 8, 2019
f534415
merge fix
kasiabulat Aug 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
scientifing notation support added, rational numbers tests fixes
  • Loading branch information
kasiabulat committed Aug 6, 2019
commit 392142a7ece2bea0556291947eb07a06fb256eea
81 changes: 74 additions & 7 deletions src/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Globalization;

namespace System.Text.Json
{
/// <summary>
Expand Down Expand Up @@ -103,6 +105,9 @@ public class JsonNumber : JsonNode, IEquatable<JsonNumber>
/// Converts the numeric value of this instance to its equivalent string representation.
/// </summary>
/// <returns>The string representation of the value of this instance.</returns>
/// <remarks>
/// Returns exactly the same value as it was set using <see cref="SetFormattedValue(string)"/>.
/// </remarks>
public override string ToString() => _value;

/// <summary>
Expand Down Expand Up @@ -169,7 +174,18 @@ public class JsonNumber : JsonNode, IEquatable<JsonNumber>
/// instead <see langword="true"/> is returned and <see cref="float.PositiveInfinity"/> (or
/// <see cref="float.NegativeInfinity"/>) is emitted.
/// </remarks>
public float GetSingle() => float.Parse(_value);
/// <remarks>
/// Allows scientific mode.
/// </remarks>
public float GetSingle()
{
if (float.TryParse(_value, out float value))
{
return value;
}

return float.Parse(_value, NumberStyles.AllowExponent, GetJsonCulture());
}

/// <summary>
/// Converts the numeric value of this instance to its <see cref="double"/> equivalent.
Expand All @@ -187,7 +203,18 @@ public class JsonNumber : JsonNode, IEquatable<JsonNumber>
/// instead <see langword="true"/> is returned and <see cref="double.PositiveInfinity"/> (or
/// <see cref="double.NegativeInfinity"/>) is emitted.
/// </remarks>
public double GetDouble() => double.Parse(_value);
/// <remarks>
/// Allows scientific mode.
/// </remarks>
public double GetDouble()
{
if (double.TryParse(_value, out double value))
{
return value;
}

return double.Parse(_value, NumberStyles.AllowExponent, GetJsonCulture());
}

/// <summary>
/// Converts the numeric value of this instance to its <see cref="sbyte"/> equivalent.
Expand Down Expand Up @@ -327,7 +354,15 @@ public class JsonNumber : JsonNode, IEquatable<JsonNumber>
/// instead <see langword="true"/> is returned and <see cref="float.PositiveInfinity"/> (or
/// <see cref="float.NegativeInfinity"/>) is emitted.
/// </remarks>
public bool TryGetSingle(out float value) => float.TryParse(_value, out value);
public bool TryGetSingle(out float value)
{
if (float.TryParse(_value, out value))
{
return true;
}

return float.TryParse(_value, NumberStyles.AllowExponent, GetJsonCulture(), out value);
}

/// <summary>
/// Converts the numeric value of this instance to its <see cref="double"/> equivalent.
Expand All @@ -347,7 +382,15 @@ public class JsonNumber : JsonNode, IEquatable<JsonNumber>
/// instead <see langword="true"/> is returned and <see cref="float.PositiveInfinity"/> (or
/// <see cref="float.NegativeInfinity"/>) is emitted.
/// </remarks>
public bool TryGetDouble(out double value) => double.TryParse(_value, out value);
public bool TryGetDouble(out double value)
{
if (double.TryParse(_value, out value))
{
return true;
}

return double.TryParse(_value, NumberStyles.AllowExponent, GetJsonCulture(), out value);
}

/// <summary>
/// Converts the numeric value of this instance to its <see cref="sbyte"/> equivalent.
Expand Down Expand Up @@ -477,13 +520,26 @@ public void SetFormattedValue(string value)
/// Changes the numeric value of this instance to represent a specified <see cref="float"/> value.
/// </summary>
/// <param name="value">The value to represent as a JSON number.</param>
public void SetSingle(float value) => _value = value.ToString();

public void SetSingle(float value)
{
if (value.Equals(float.PositiveInfinity) || value.Equals(float.NegativeInfinity))
{
throw new FormatException("Provided value does not represent legal JSON number.");
}
_value = value.ToString();
}
/// <summary>
/// Changes the numeric value of this instance to represent a specified <see cref="double"/> value.
/// </summary>
/// <param name="value">The value to represent as a JSON number.</param>
public void SetDouble(double value) => _value = value.ToString();
public void SetDouble(double value)
{
if(value.Equals(double.PositiveInfinity) || value.Equals(double.NegativeInfinity))
{
throw new FormatException("Provided value does not represent legal JSON number.");
}
_value = value.ToString();
}

/// <summary>
/// Changes the numeric value of this instance to represent a specified <see cref="sbyte"/> value.
Expand Down Expand Up @@ -636,5 +692,16 @@ public void SetFormattedValue(string value)
/// <see langword="false"/> otherwise.
/// </returns>
public static bool operator !=(JsonNumber left, JsonNumber right) => left?._value != right?._value;

/// <summary>
/// Returns <see cref="CultureInfo"/> object with number decimal separator set to `.`
/// </summary>
/// <returns></returns>
private CultureInfo GetJsonCulture()
{
CultureInfo jsonCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
jsonCulture.NumberFormat.NumberDecimalSeparator = ".";
return jsonCulture;
}
}
}
78 changes: 71 additions & 7 deletions src/System.Text.Json/tests/JsonNumberTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace System.Text.Json.Tests
{
public static class JsonNumberTests
{
private const int Precision = 5;

private delegate bool TryGetValue<T>(JsonNumber number, out T result);

private static void TestInitialization<T>(
Expand All @@ -29,23 +31,49 @@ private static void TestInitialization<T>(
AssertValue(value, number, getter, tryGetter);

// String constructor:
number = new JsonNumber(value.ToString());
number = new JsonNumber(value.ToString().Replace(',','.'));
AssertValue(value, number, getter, tryGetter);

// Implicit cast:
number = implicitCaster(value);
AssertValue(value, number, getter, tryGetter);
}

private static void AssertWithPrecision<T>(
double value,
JsonNumber number,
Func<JsonNumber, T> getter,
TryGetValue<T> tryGetter)
{
Assert.Equal(value, Convert.ToDouble(getter(number)), Precision);
Assert.True(tryGetter(number, out T tryGetterResult));
Assert.Equal(value, Convert.ToDouble(tryGetterResult), Precision);
}

private static void AssertValue<T>(
T value,
JsonNumber number,
Func<JsonNumber, T> getter,
TryGetValue<T> tryGetter)
{
Assert.Equal(value, getter(number));
Assert.True(tryGetter(number, out T result));
Assert.Equal(value, result);

switch (value)
{
case double doubleValue:
AssertWithPrecision(doubleValue, number, getter, tryGetter);
return;
case float floatValue:
AssertWithPrecision(Convert.ToDouble(floatValue), number, getter, tryGetter);
return;
case decimal decimalValue:
AssertWithPrecision(Convert.ToDouble(decimalValue), number, getter, tryGetter);
return;
default:
Assert.Equal(value, getter(number));
Assert.True(tryGetter(number, out T result));
Assert.Equal(value, result);
return;
}
}

[Fact]
Expand Down Expand Up @@ -370,11 +398,11 @@ public static void TestUpcasts()

Assert.Equal(value, jsonNumber.GetSingle());
Assert.True(jsonNumber.TryGetSingle(out float floatResult));
Assert.Equal(value, floatResult);
Assert.Equal(value, floatResult, Precision);

Assert.Equal(value, jsonNumber.GetDouble());
Assert.True(jsonNumber.TryGetDouble(out double doubleResult));
Assert.Equal(value, doubleResult);
Assert.Equal(value, doubleResult, Precision);

Assert.Equal(value, (byte)jsonNumber.GetSByte());
Assert.True(jsonNumber.TryGetSByte(out sbyte sbyteResult));
Expand All @@ -394,7 +422,7 @@ public static void TestUpcasts()

Assert.Equal(value, jsonNumber.GetDecimal());
Assert.True(jsonNumber.TryGetDecimal(out decimal decimalResult));
Assert.Equal(value, decimalResult);
Assert.Equal(value, decimalResult, Precision);
}

[Fact]
Expand Down Expand Up @@ -472,6 +500,42 @@ public static void TestRationalGetMismatches()
Assert.Throws<FormatException>(() => jsonNumber.GetUInt64());
}

[InlineData(float.PositiveInfinity)]
[InlineData(float.NegativeInfinity)]
[Theory]
public static void TestFloatninities(float value)
{
Assert.Throws<FormatException>(() => new JsonNumber(value));
}

[InlineData(double.PositiveInfinity)]
[InlineData(double.NegativeInfinity)]
[Theory]
public static void TestDoubleIninities(double value)
{
Assert.Throws<FormatException > (() => new JsonNumber(value));
}

[Fact]
public static void TestScientificNotation()
{
var jsonNumber = new JsonNumber("5e6");
Assert.Equal(5000000, jsonNumber.GetSingle(), Precision);
Assert.Equal(5000000, jsonNumber.GetDouble(), Precision);

jsonNumber = new JsonNumber("3.14e0");
Assert.Equal(3.14, jsonNumber.GetSingle(), Precision);
Assert.Equal(3.14, jsonNumber.GetDouble(), Precision);

jsonNumber = new JsonNumber("7e-3");
Assert.Equal(0.007, jsonNumber.GetSingle(), Precision);
Assert.Equal(0.007, jsonNumber.GetDouble(), Precision);

jsonNumber = new JsonNumber("-7e-3");
Assert.Equal(-0.007, jsonNumber.GetSingle(), Precision);
Assert.Equal(-0.007, jsonNumber.GetDouble(), Precision);
}

[Fact]
public static void TestChangingTypes()
{
Expand Down