From: Stephen Toub Date: Fri, 25 Jan 2019 03:43:22 +0000 (-0500) Subject: Fix culture handling in legacy System.Json library (dotnet/corefx#34811) X-Git-Tag: submit/tizen/20210909.063632~11031^2~2614 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=294ac9a70809892eb9ce5b5e0375d5085c6d180d;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Fix culture handling in legacy System.Json library (dotnet/corefx#34811) * Fix System.Json code using NumberFormatInfo.InvariantInfo The intention here was obviously to use invariant culture, but NumberFormatInfo will be ignored for various primitive types that don't respect NFI, e.g. TimeSpan, which respects DateTimeFormatInfo. * Fix handling of culture in System.Json tests In particular, CultureInfo.CurrentCulture should not be modified in-process in tests, as on UWP it bleeds across threads. Commit migrated from https://github.com/dotnet/corefx/commit/f398b6f7c3d08d8e437939cbd9ef29cb3beda1db --- diff --git a/src/libraries/System.Json/src/System/Json/JsonPrimitive.cs b/src/libraries/System.Json/src/System/Json/JsonPrimitive.cs index 754783b..86a74e9 100644 --- a/src/libraries/System.Json/src/System/Json/JsonPrimitive.cs +++ b/src/libraries/System.Json/src/System/Json/JsonPrimitive.cs @@ -159,8 +159,8 @@ namespace System.Json case JsonType.Number: string s = _value is float || _value is double ? - ((IFormattable)_value).ToString("R", NumberFormatInfo.InvariantInfo) : // Use "round-trip" format - ((IFormattable)_value).ToString("G", NumberFormatInfo.InvariantInfo); + ((IFormattable)_value).ToString("R", CultureInfo.InvariantCulture) : // Use "round-trip" format + ((IFormattable)_value).ToString("G", CultureInfo.InvariantCulture); return s == "NaN" || s == "Infinity" || s == "-Infinity" ? "\"" + s + "\"" : s; diff --git a/src/libraries/System.Json/src/System/Json/JsonValue.cs b/src/libraries/System.Json/src/System/Json/JsonValue.cs index 4fdae75..3a6a14c 100644 --- a/src/libraries/System.Json/src/System/Json/JsonValue.cs +++ b/src/libraries/System.Json/src/System/Json/JsonValue.cs @@ -350,7 +350,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToBoolean(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToBoolean(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator byte (JsonValue value) @@ -360,7 +360,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToByte(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToByte(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator char (JsonValue value) @@ -370,7 +370,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToChar(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToChar(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator decimal (JsonValue value) @@ -380,14 +380,14 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToDecimal(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToDecimal(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator double (JsonValue value) { if (value == null) throw new ArgumentNullException(nameof(value)); - return Convert.ToDouble(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToDouble(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator float (JsonValue value) @@ -397,7 +397,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToSingle(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToSingle(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator int (JsonValue value) @@ -407,7 +407,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToInt32(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToInt32(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator long (JsonValue value) @@ -417,7 +417,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToInt64(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToInt64(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] @@ -428,7 +428,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToSByte(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToSByte(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator short (JsonValue value) @@ -438,7 +438,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToInt16(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToInt16(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator string (JsonValue value) @@ -456,7 +456,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToUInt32(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToUInt32(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] @@ -467,7 +467,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToUInt64(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToUInt64(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] @@ -478,7 +478,7 @@ namespace System.Json throw new ArgumentNullException(nameof(value)); } - return Convert.ToUInt16(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo); + return Convert.ToUInt16(((JsonPrimitive)value).Value, CultureInfo.InvariantCulture); } public static implicit operator DateTime(JsonValue value) diff --git a/src/libraries/System.Json/tests/JsonPrimitiveTests.cs b/src/libraries/System.Json/tests/JsonPrimitiveTests.cs index c19c41f..c30caa2 100644 --- a/src/libraries/System.Json/tests/JsonPrimitiveTests.cs +++ b/src/libraries/System.Json/tests/JsonPrimitiveTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. +using System.Globalization; using System.IO; using System.Text; using Xunit; @@ -76,13 +77,13 @@ namespace System.Json.Tests [Fact] public void ToString_DateTimeOffset() { - ToString(new JsonPrimitive(DateTimeOffset.MinValue), DateTimeOffset.MinValue.ToString("G")); + ToString(new JsonPrimitive(DateTimeOffset.MinValue), DateTimeOffset.MinValue.ToString("G", CultureInfo.InvariantCulture)); } [Fact] public void ToString_TimeSpan() { - ToString(new JsonPrimitive(TimeSpan.Zero), TimeSpan.Zero.ToString("G")); + ToString(new JsonPrimitive(TimeSpan.Zero), TimeSpan.Zero.ToString("G", CultureInfo.InvariantCulture)); } private void ToString(JsonValue primitive, string expected) diff --git a/src/libraries/System.Json/tests/JsonValueTests.cs b/src/libraries/System.Json/tests/JsonValueTests.cs index 06d61d8..ea64ddc 100644 --- a/src/libraries/System.Json/tests/JsonValueTests.cs +++ b/src/libraries/System.Json/tests/JsonValueTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // See the LICENSE file in the project root for more information. +using System.Diagnostics; using System.IO; using System.Text; using System.Globalization; @@ -10,7 +11,7 @@ using System.Collections.Generic; namespace System.Json.Tests { - public class JsonValueTests + public class JsonValueTests : RemoteExecutorTestBase { [Fact] public void JsonValue_Load_LoadWithTrailingCommaInDictionary() @@ -235,19 +236,14 @@ namespace System.Json.Tests [InlineData("0.000000000000000000000000000011", 1.1E-29)] public void JsonValue_Parse_Double(string json, double expected) { - foreach (string culture in new[] { "en", "fr", "de" }) + RemoteInvoke((jsonInner, expectedInner) => { - CultureInfo old = CultureInfo.CurrentCulture; - try + foreach (string culture in new[] { "en", "fr", "de" }) { CultureInfo.CurrentCulture = new CultureInfo(culture); - Assert.Equal(expected, (double)JsonValue.Parse(json)); + Assert.Equal(double.Parse(expectedInner, CultureInfo.InvariantCulture), (double)JsonValue.Parse(jsonInner)); } - finally - { - CultureInfo.CurrentCulture = old; - } - } + }, json, expected.ToString("R", CultureInfo.InvariantCulture)).Dispose(); } // Convert a number to json and parse the string, then compare the result to the original value @@ -275,19 +271,15 @@ namespace System.Json.Tests [InlineData(1.123456789e-28)] // Values around the smallest positive decimal value public void JsonValue_Parse_Double_ViaJsonPrimitive(double number) { - foreach (string culture in new[] { "en", "fr", "de" }) + RemoteInvoke(numberText => { - CultureInfo old = CultureInfo.CurrentCulture; - try + double numberInner = double.Parse(numberText, CultureInfo.InvariantCulture); + foreach (string culture in new[] { "en", "fr", "de" }) { CultureInfo.CurrentCulture = new CultureInfo(culture); - Assert.Equal(number, (double)JsonValue.Parse(new JsonPrimitive(number).ToString())); + Assert.Equal(numberInner, (double)JsonValue.Parse(new JsonPrimitive(numberInner).ToString())); } - finally - { - CultureInfo.CurrentCulture = old; - } - } + }, number.ToString("R", CultureInfo.InvariantCulture)).Dispose(); } [Fact] diff --git a/src/libraries/System.Json/tests/System.Json.Tests.csproj b/src/libraries/System.Json/tests/System.Json.Tests.csproj index 0a35ca1..8ae2a93 100644 --- a/src/libraries/System.Json/tests/System.Json.Tests.csproj +++ b/src/libraries/System.Json/tests/System.Json.Tests.csproj @@ -9,5 +9,9 @@ + + {69e46a6f-9966-45a5-8945-2559fe337827} + RemoteExecutorConsoleApp + \ No newline at end of file