Skip to content

Commit 161deec

Browse files
authored
Add functional custom JsonConverter tests for Int128/UInt128/Half (#74254)
* Add functional custom JsonConverter tests for Int128/UInt128/Half * use invariant culture
1 parent f616642 commit 161deec

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using System.Globalization;
6+
using System.Numerics;
7+
using Xunit;
8+
9+
namespace System.Text.Json.Serialization.Tests
10+
{
11+
public static class ConvertersForUnsupportedTypesFunctionalTests
12+
{
13+
[Theory]
14+
[MemberData(nameof(GetTestData))]
15+
public static void RoundtripValues<T>(string expectedValueAsString, T value)
16+
{
17+
JsonSerializerOptions options = new()
18+
{
19+
Converters = { new Int128Converter(), new UInt128Converter(), new HalfConverter(), new BigIntegerConverter() }
20+
};
21+
22+
ClassWithProperty<T> wrappedValue = new()
23+
{
24+
Property = value
25+
};
26+
27+
string json = JsonSerializer.Serialize(value, options);
28+
Assert.Equal(expectedValueAsString, json);
29+
30+
T deserializedValue = JsonSerializer.Deserialize<T>(json, options);
31+
Assert.Equal(value, deserializedValue);
32+
33+
json = JsonSerializer.Serialize(wrappedValue, options);
34+
Assert.Equal($"{{\"Property\":{expectedValueAsString}}}", json);
35+
ClassWithProperty<T> deserializedWrappedValue = JsonSerializer.Deserialize<ClassWithProperty<T>>(json, options);
36+
Assert.Equal(wrappedValue.Property, deserializedWrappedValue.Property);
37+
}
38+
39+
public static IEnumerable<object[]> GetTestData()
40+
{
41+
NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
42+
43+
yield return GetTestCase("0", Int128.Zero);
44+
yield return GetTestCase("-1", new Int128(ulong.MaxValue, ulong.MaxValue));
45+
yield return GetTestCase(Int128.MaxValue.ToString(nfi), Int128.MaxValue);
46+
yield return GetTestCase(ulong.MaxValue.ToString(nfi), new Int128(0UL, ulong.MaxValue));
47+
yield return GetTestCase(ulong.MaxValue.ToString(nfi) + "173", new Int128(0UL, ulong.MaxValue) * 1000 + 173);
48+
49+
yield return GetTestCase("0", UInt128.Zero);
50+
yield return GetTestCase(UInt128.MaxValue.ToString(nfi), UInt128.MaxValue);
51+
yield return GetTestCase(ulong.MaxValue.ToString(nfi), new UInt128(0UL, ulong.MaxValue));
52+
yield return GetTestCase(ulong.MaxValue.ToString(nfi) + "173", new UInt128(0UL, ulong.MaxValue) * 1000 + 173);
53+
54+
yield return GetTestCase("0", Half.Zero);
55+
yield return GetTestCase(Half.MaxValue.ToString(nfi), Half.MaxValue);
56+
yield return GetTestCase(Half.MinValue.ToString(nfi), Half.MinValue);
57+
yield return GetTestCase(((Half)1.45f).ToString(nfi), (Half)1.45f);
58+
59+
yield return GetTestCase("0", BigInteger.Zero);
60+
yield return GetTestCase("1", BigInteger.One);
61+
yield return GetTestCase(ulong.MaxValue.ToString(nfi), (BigInteger)ulong.MaxValue);
62+
yield return GetTestCase("-123", (BigInteger)(-123));
63+
64+
static object[] GetTestCase(string expectedValue, object value) => new object[] { expectedValue, value };
65+
}
66+
67+
internal class ClassWithProperty<T>
68+
{
69+
public T Property { get; set; }
70+
}
71+
72+
internal class HalfConverter : SimpleConverter<Half>
73+
{
74+
public override Half Parse(string value) => Half.Parse(value, CultureInfo.InvariantCulture.NumberFormat);
75+
public override string ToString(Half value) => value.ToString(CultureInfo.InvariantCulture.NumberFormat);
76+
}
77+
78+
internal class UInt128Converter : SimpleConverter<UInt128>
79+
{
80+
public override UInt128 Parse(string value) => UInt128.Parse(value, CultureInfo.InvariantCulture.NumberFormat);
81+
public override string ToString(UInt128 value) => value.ToString(CultureInfo.InvariantCulture.NumberFormat);
82+
}
83+
84+
internal class Int128Converter : SimpleConverter<Int128>
85+
{
86+
public override Int128 Parse(string value) => Int128.Parse(value, CultureInfo.InvariantCulture.NumberFormat);
87+
public override string ToString(Int128 value) => value.ToString(CultureInfo.InvariantCulture.NumberFormat);
88+
}
89+
90+
internal class BigIntegerConverter : SimpleConverter<BigInteger>
91+
{
92+
public override BigInteger Parse(string value) => BigInteger.Parse(value, CultureInfo.InvariantCulture.NumberFormat);
93+
public override string ToString(BigInteger value) => value.ToString(CultureInfo.InvariantCulture.NumberFormat);
94+
}
95+
96+
internal abstract class SimpleConverter<T> : JsonConverter<T>
97+
{
98+
public abstract T Parse(string value);
99+
public abstract string ToString(T value);
100+
101+
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
102+
{
103+
if (reader.HasValueSequence)
104+
{
105+
return Parse(Encoding.UTF8.GetString(reader.ValueSequence));
106+
}
107+
else
108+
{
109+
return Parse(Encoding.UTF8.GetString(reader.ValueSpan));
110+
}
111+
}
112+
113+
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
114+
{
115+
writer.WriteRawValue(ToString(value));
116+
}
117+
}
118+
}
119+
}

src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@
226226
<Compile Include="Utf8JsonWriterTests.cs" />
227227
<Compile Include="Utf8JsonWriterTests.WriteRaw.cs" />
228228
</ItemGroup>
229+
<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
230+
<Compile Include="Serialization\ConvertersForUnsupportedTypesFunctionalTests.cs" />
231+
</ItemGroup>
229232
<ItemGroup>
230233
<Compile Include="..\..\src\System\Text\Json\BitStack.cs" Link="BitStack.cs" />
231234
</ItemGroup>

0 commit comments

Comments
 (0)