Skip to content

Commit 78839a4

Browse files
authored
CSHARP-5250: Change Decimal128 default serial to Bson.Decimal128 (#1441)
* CSHARP-5250: Change Decimal128 default serialization to Bson.Decimal128 * Test correction * Corrections according to review * Corrected tests * Small fix * Fixed errors
1 parent 93a3494 commit 78839a4

File tree

10 files changed

+69
-25
lines changed

10 files changed

+69
-25
lines changed

src/MongoDB.Bson/Serialization/Serializers/Decimal128Serializer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ namespace MongoDB.Bson.Serialization.Serializers
2525
public class Decimal128Serializer : StructSerializerBase<Decimal128>, IRepresentationConfigurable<Decimal128Serializer>, IRepresentationConverterConfigurable<Decimal128Serializer>
2626
{
2727
#region static
28-
private static readonly Decimal128Serializer __decimal128Instance = new Decimal128Serializer(BsonType.Decimal128);
28+
private static readonly Decimal128Serializer __instance = new Decimal128Serializer();
2929

3030
/// <summary>
3131
/// Gets a cached instance of a Decimal128Serializer with Decimal128 representation.
3232
/// </summary>
33-
public static Decimal128Serializer Decimal128Instance => __decimal128Instance;
33+
public static Decimal128Serializer Instance => __instance;
3434
#endregion
3535

3636
// private fields
@@ -42,7 +42,7 @@ public class Decimal128Serializer : StructSerializerBase<Decimal128>, IRepresent
4242
/// Initializes a new instance of the <see cref="Decimal128Serializer"/> class.
4343
/// </summary>
4444
public Decimal128Serializer()
45-
: this(BsonType.String)
45+
: this(BsonType.Decimal128)
4646
{
4747
}
4848

src/MongoDB.Bson/Serialization/Serializers/DecimalSerializer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ namespace MongoDB.Bson.Serialization.Serializers
2525
public class DecimalSerializer : StructSerializerBase<decimal>, IRepresentationConfigurable<DecimalSerializer>, IRepresentationConverterConfigurable<DecimalSerializer>
2626
{
2727
#region static
28-
private static readonly DecimalSerializer __decimal128Instance = new DecimalSerializer(BsonType.Decimal128);
28+
private static readonly DecimalSerializer __instance = new DecimalSerializer();
2929

3030
/// <summary>
3131
/// Gets a cached instance of a DecimalSerializer with Decimal128 representation.
3232
/// </summary>
33-
public static DecimalSerializer Decimal128Instance => __decimal128Instance;
33+
public static DecimalSerializer Instance => __instance;
3434
#endregion
3535

3636
// private fields
@@ -42,7 +42,7 @@ public class DecimalSerializer : StructSerializerBase<decimal>, IRepresentationC
4242
/// Initializes a new instance of the <see cref="DecimalSerializer"/> class.
4343
/// </summary>
4444
public DecimalSerializer()
45-
: this(BsonType.String)
45+
: this(BsonType.Decimal128)
4646
{
4747
}
4848

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/BinaryExpressionToAggregationExpressionTranslator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public static AggregationExpression Translate(TranslationContext context, Binary
128128
Type t when t == typeof(ulong) => new UInt64Serializer(),
129129
Type t when t == typeof(float) => new SingleSerializer(),
130130
Type t when t == typeof(double) => new DoubleSerializer(),
131-
Type t when t == typeof(decimal) => DecimalSerializer.Decimal128Instance,
131+
Type t when t == typeof(decimal) => DecimalSerializer.Instance,
132132
Type { IsConstructedGenericType: true } t when t.GetGenericTypeDefinition() == typeof(Nullable<>) => (IBsonSerializer)Activator.CreateInstance(typeof(NullableSerializer<>).MakeGenericType(t.GenericTypeArguments[0])),
133133
Type { IsArray: true } t => (IBsonSerializer)Activator.CreateInstance(typeof(ArraySerializer<>).MakeGenericType(t.GetElementType())),
134134
_ => context.KnownSerializersRegistry.GetSerializer(expression) // Required for Coalesce

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ConvertExpressionToAggregationExpressionTranslator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ private static AggregationExpression Translate(UnaryExpression expression, Type
116116
case "MongoDB.Bson.ObjectId": to = "objectId"; serializer = ObjectIdSerializer.Instance; break;
117117
case "System.Boolean": to = "bool"; serializer = BooleanSerializer.Instance; break;
118118
case "System.DateTime": to = "date"; serializer = DateTimeSerializer.Instance; break;
119-
case "System.Decimal": to = "decimal"; serializer = DecimalSerializer.Decimal128Instance; break; // not the default representation
119+
case "System.Decimal": to = "decimal"; serializer = DecimalSerializer.Instance; break; // not the default representation
120120
case "System.Double": to = "double"; serializer = DoubleSerializer.Instance; break;
121121
case "System.Int32": to = "int"; serializer = Int32Serializer.Instance; break;
122122
case "System.Int64": to = "long"; serializer = Int64Serializer.Instance; break;

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/MemberExpressionToFilterFieldTranslator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ internal static class MemberExpressionToFilterFieldTranslator
2727
{
2828
private static readonly IBsonSerializer<Nullable<bool>> __nullableBooleanSerializer = new NullableSerializer<bool>(BooleanSerializer.Instance);
2929
private static readonly IBsonSerializer<Nullable<DateTime>> __nullableDateTimeSerializer = new NullableSerializer<DateTime>(DateTimeSerializer.UtcInstance);
30-
private static readonly IBsonSerializer<Nullable<Decimal>> __nullableDecimalSerializer = new NullableSerializer<Decimal>(DecimalSerializer.Decimal128Instance);
31-
private static readonly IBsonSerializer<Nullable<Decimal128>> __nullableDecimal128Serializer = new NullableSerializer<Decimal128>(Decimal128Serializer.Decimal128Instance);
30+
private static readonly IBsonSerializer<Nullable<Decimal>> __nullableDecimalSerializer = new NullableSerializer<Decimal>(DecimalSerializer.Instance);
31+
private static readonly IBsonSerializer<Nullable<Decimal128>> __nullableDecimal128Serializer = new NullableSerializer<Decimal128>(Decimal128Serializer.Instance);
3232
private static readonly IBsonSerializer<Nullable<double>> __nullableDoubleSerializer = new NullableSerializer<Double>(DoubleSerializer.Instance);
3333
private static readonly IBsonSerializer<Nullable<Guid>> __nullableGuidSerializer = new NullableSerializer<Guid>(GuidSerializer.StandardInstance);
3434
private static readonly IBsonSerializer<Nullable<int>> __nullableInt32Serializer = new NullableSerializer<int>(Int32Serializer.Instance);
@@ -63,8 +63,8 @@ public static AstFilterField Translate(TranslationContext context, MemberExpress
6363
case "AsBsonValue": return AstFilter.Field(field.Path, fieldSerializer);
6464
case "AsByteArray": return AstFilter.Field(field.Path, ByteArraySerializer.Instance);
6565
case "AsDateTime": return AstFilter.Field(field.Path, DateTimeSerializer.UtcInstance);
66-
case "AsDecimal": return AstFilter.Field(field.Path, DecimalSerializer.Decimal128Instance);
67-
case "AsDecimal128": return AstFilter.Field(field.Path, Decimal128Serializer.Decimal128Instance);
66+
case "AsDecimal": return AstFilter.Field(field.Path, DecimalSerializer.Instance);
67+
case "AsDecimal128": return AstFilter.Field(field.Path, Decimal128Serializer.Instance);
6868
case "AsDouble": return AstFilter.Field(field.Path, DoubleSerializer.Instance);
6969
case "AsGuid": return AstFilter.Field(field.Path, GuidSerializer.StandardInstance);
7070
case "AsInt32": return AstFilter.Field(field.Path, Int32Serializer.Instance);

tests/MongoDB.Bson.Tests/Serialization/Serializers/Decimal128SerializerTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,39 @@
1717
using FluentAssertions;
1818
using MongoDB.Bson.Serialization.Options;
1919
using MongoDB.Bson.Serialization.Serializers;
20+
using MongoDB.TestHelpers.XunitExtensions;
2021
using Xunit;
2122

2223
namespace MongoDB.Bson.Tests.Serialization.Serializers
2324
{
2425
public class Decimal128SerializerTests
2526
{
27+
[Fact]
28+
public void Constructor_with_no_arguments_should_return_expected_result()
29+
{
30+
var subject = new Decimal128Serializer();
31+
32+
subject.Representation.Should().Be(BsonType.Decimal128);
33+
}
34+
35+
[Theory]
36+
[ParameterAttributeData]
37+
public void Constructor_with_representation_should_return_expected_result(
38+
[Values(BsonType.Decimal128, BsonType.Int32, BsonType.Int64, BsonType.String, BsonType.Double)] BsonType representation)
39+
{
40+
var subject = new Decimal128Serializer(representation);
41+
42+
subject.Representation.Should().Be(representation);
43+
}
44+
45+
[Fact]
46+
public void Constructor_with_representation_should_throw_when_representation_is_invalid()
47+
{
48+
var exception = Record.Exception(() => new Decimal128Serializer(BsonType.Null));
49+
50+
exception.Should().BeOfType<ArgumentException>();
51+
}
52+
2653
[Fact]
2754
public void Equals_derived_should_return_false()
2855
{
@@ -108,6 +135,23 @@ public void GetHashCode_should_return_zero()
108135
result.Should().Be(0);
109136
}
110137

138+
[Theory]
139+
[ParameterAttributeData]
140+
public void WithRepresentation_should_return_expected_result(
141+
[Values(BsonType.Decimal128, BsonType.Int32, BsonType.Int64, BsonType.String, BsonType.Double)] BsonType oldRepresentation,
142+
[Values(BsonType.Decimal128, BsonType.Int32, BsonType.Int64, BsonType.String, BsonType.Double)] BsonType newRepresentation)
143+
{
144+
var subject = new Decimal128Serializer(oldRepresentation);
145+
146+
var result = subject.WithRepresentation(newRepresentation);
147+
148+
result.Representation.Should().Be(newRepresentation);
149+
if (newRepresentation == oldRepresentation)
150+
{
151+
result.Should().BeSameAs(subject);
152+
}
153+
}
154+
111155
public class DerivedFromDecimal128Serializer : Decimal128Serializer
112156
{
113157
}

tests/MongoDB.Bson.Tests/Serialization/Serializers/NetPrimitiveSerializerTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ public void TestMin()
10941094
S = decimal.MinValue
10951095
};
10961096
var json = obj.ToJson();
1097-
var expected = "{ 'X' : '#S', 'A' : [-1, -1, -1, -2147483648], 'D128' : NumberDecimal('#D128'), 'D' : #D, 'I' : #I, 'L' : NumberLong('#L'), 'S' : '#S' }";
1097+
var expected = "{ 'X' : NumberDecimal('#D128'), 'A' : [-1, -1, -1, -2147483648], 'D128' : NumberDecimal('#D128'), 'D' : #D, 'I' : #I, 'L' : NumberLong('#L'), 'S' : '#S' }";
10981098
expected = expected.Replace("#S", JsonConvert.ToString(decimal.MinValue));
10991099
expected = expected.Replace("#D128", "-9.999999999999999999999999999999999E+6144");
11001100
expected = expected.Replace("#D", "-1.7976931348623157E+308");
@@ -1122,7 +1122,7 @@ public void TestMax()
11221122
S = decimal.MaxValue
11231123
};
11241124
var json = obj.ToJson();
1125-
var expected = "{ 'X' : '#S', 'A' : [-1, -1, -1, 0], 'D128' : NumberDecimal('#D128'), 'D' : #D, 'I' : #I, 'L' : NumberLong('#L'), 'S' : '#S' }";
1125+
var expected = "{ 'X' : NumberDecimal('#D128'), 'A' : [-1, -1, -1, 0], 'D128' : NumberDecimal('#D128'), 'D' : #D, 'I' : #I, 'L' : NumberLong('#L'), 'S' : '#S' }";
11261126
expected = expected.Replace("#S", JsonConvert.ToString(decimal.MaxValue));
11271127
expected = expected.Replace("#D128", "9.999999999999999999999999999999999E+6144");
11281128
expected = expected.Replace("#D", "1.7976931348623157E+308");
@@ -1150,7 +1150,7 @@ public void TestMinusOne()
11501150
S = decimal.MinusOne
11511151
};
11521152
var json = obj.ToJson();
1153-
var expected = "{ 'X' : '-1', 'A' : [1, 0, 0, -2147483648], 'D128' : NumberDecimal('-1'), 'D' : -1.0, 'I' : -1, 'L' : NumberLong(-1), 'S' : '-1' }".Replace("'", "\"");
1153+
var expected = "{ 'X' : NumberDecimal('-1'), 'A' : [1, 0, 0, -2147483648], 'D128' : NumberDecimal('-1'), 'D' : -1.0, 'I' : -1, 'L' : NumberLong(-1), 'S' : '-1' }".Replace("'", "\"");
11541154
Assert.Equal(expected, json);
11551155

11561156
var bson = obj.ToBson();
@@ -1172,7 +1172,7 @@ public void TestZero()
11721172
S = decimal.Zero
11731173
};
11741174
var json = obj.ToJson();
1175-
var expected = "{ 'X' : '0', 'A' : [0, 0, 0, 0], 'D128' : NumberDecimal('0'), 'D' : 0.0, 'I' : 0, 'L' : NumberLong(0), 'S' : '0' }".Replace("'", "\"");
1175+
var expected = "{ 'X' : NumberDecimal('0'), 'A' : [0, 0, 0, 0], 'D128' : NumberDecimal('0'), 'D' : 0.0, 'I' : 0, 'L' : NumberLong(0), 'S' : '0' }".Replace("'", "\"");
11761176
Assert.Equal(expected, json);
11771177

11781178
var bson = obj.ToBson();
@@ -1194,7 +1194,7 @@ public void TestOne()
11941194
S = decimal.One
11951195
};
11961196
var json = obj.ToJson();
1197-
var expected = "{ 'X' : '1', 'A' : [1, 0, 0, 0], 'D128' : NumberDecimal('1'), 'D' : 1.0, 'I' : 1, 'L' : NumberLong(1), 'S' : '1' }".Replace("'", "\"");
1197+
var expected = "{ 'X' : NumberDecimal('1'), 'A' : [1, 0, 0, 0], 'D128' : NumberDecimal('1'), 'D' : 1.0, 'I' : 1, 'L' : NumberLong(1), 'S' : '1' }".Replace("'", "\"");
11981198
Assert.Equal(expected, json);
11991199

12001200
var bson = obj.ToBson();
@@ -1216,7 +1216,7 @@ public void TestOnePointThree()
12161216
S = 1.3m
12171217
};
12181218
var json = obj.ToJson();
1219-
var expected = "{ 'X' : '1.3', 'A' : [13, 0, 0, 65536], 'D128' : NumberDecimal('1.3'), 'D' : 1.3, 'I' : 1, 'L' : NumberLong(1), 'S' : '1.3' }".Replace("'", "\"");
1219+
var expected = "{ 'X' : NumberDecimal('1.3'), 'A' : [13, 0, 0, 65536], 'D128' : NumberDecimal('1.3'), 'D' : 1.3, 'I' : 1, 'L' : NumberLong(1), 'S' : '1.3' }".Replace("'", "\"");
12201220
Assert.Equal(expected, json);
12211221

12221222
var bson = obj.ToBson();
@@ -1238,7 +1238,7 @@ public void TestOnePointFive()
12381238
S = 1.5m
12391239
};
12401240
var json = obj.ToJson();
1241-
var expected = "{ 'X' : '1.5', 'A' : [15, 0, 0, 65536], 'D128' : NumberDecimal('1.5'), 'D' : 1.5, 'I' : 1, 'L' : NumberLong(1), 'S' : '1.5' }".Replace("'", "\"");
1241+
var expected = "{ 'X' : NumberDecimal('1.5'), 'A' : [15, 0, 0, 65536], 'D128' : NumberDecimal('1.5'), 'D' : 1.5, 'I' : 1, 'L' : NumberLong(1), 'S' : '1.5' }".Replace("'", "\"");
12421242
Assert.Equal(expected, json);
12431243

12441244
var bson = obj.ToBson();

tests/MongoDB.Bson.Tests/Serialization/Serializers/ObjectSerializerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public void TestDecimal()
138138
var c = new C { Obj = value };
139139

140140
var json = c.ToJson();
141-
json.Should().Be("{ \"Obj\" : { \"_t\" : \"System.Decimal\", \"_v\" : \"1.5\" } }");
141+
json.Should().Be("""{ "Obj" : { "_t" : "System.Decimal", "_v" : NumberDecimal("1.5") } }""");
142142

143143
var bson = c.ToBson();
144144
var rehydrated = BsonSerializer.Deserialize<C>(bson);

tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4368Tests.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
using MongoDB.Bson.Serialization;
2525
using MongoDB.Bson.Serialization.Serializers;
2626
using MongoDB.Bson.TestHelpers;
27-
using MongoDB.Driver.Linq;
2827
using MongoDB.Driver.Linq.Linq3Implementation.Serializers;
2928
using Xunit;
3029

@@ -79,11 +78,11 @@ public static TestCase CreateTestCase<TValue>(
7978
CreateTestCase<DateTime>("ISODate('2021-01-02T03:04:05.123')", x => (BsonValue)x.V),
8079
CreateTestCase<DateTime?>("ISODate('2021-01-02T03:04:05.123')", x => (BsonValue)x.V),
8180
CreateTestCase<DateTime?>("null", x => (BsonValue)x.V),
82-
CreateTestCase<decimal>("'1'", x => (BsonValue)x.V),
83-
CreateTestCase<decimal?>("'1'", x => (BsonValue)x.V),
81+
CreateTestCase<decimal>("{ $numberDecimal : '1.0' }", x => (BsonValue)x.V),
82+
CreateTestCase<decimal?>("{ $numberDecimal : '1.0' }", x => (BsonValue)x.V),
8483
CreateTestCase<decimal?>("null", x => (BsonValue)x.V),
85-
CreateTestCase<Decimal128>("'1'", x => (BsonValue)x.V),
86-
CreateTestCase<Decimal128?>("'1'", x => (BsonValue)x.V),
84+
CreateTestCase<Decimal128>("{ $numberDecimal : '1.0' }", x => (BsonValue)x.V),
85+
CreateTestCase<Decimal128?>("{ $numberDecimal : '1.0' }", x => (BsonValue)x.V),
8786
CreateTestCase<Decimal128?>("null", x => (BsonValue)x.V),
8887
CreateTestCase<double>("{ $numberDouble : '1.0' }", x => (BsonValue)x.V),
8988
CreateTestCase<double?>("{ $numberDouble : '1.0' }", x => (BsonValue)x.V),

tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NegateExpressionToAggregationExpressionTranslatorTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ private class Data
129129
public long Long { get; set; }
130130
public float Single { get; set; }
131131
public double Double { get; set; }
132+
[BsonRepresentation(BsonType.String)]
132133
public decimal DecimalAsString { get; set; }
133134
[BsonRepresentation(BsonType.Decimal128)]
134135
public decimal DecimalAsDecimal128 { get; set; }

0 commit comments

Comments
 (0)