Skip to content

Commit 9a50493

Browse files
authored
Handle parameterless ctors in structs in STJ's ReflectionEmitMemberAccessor (#62989)
* Add boxing for parameterless ctors in structs (C# 10 feature) during dynamic code generation * move tests to Common * fix tests * Address feedback
1 parent 64649da commit 9a50493

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor
4949
else
5050
{
5151
generator.Emit(OpCodes.Newobj, realMethod);
52+
if (type.IsValueType)
53+
{
54+
// Since C# 10 it's now possible to have parameterless constructors in structs
55+
generator.Emit(OpCodes.Box, type);
56+
}
5257
}
5358

5459
generator.Emit(OpCodes.Ret);

src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,5 +1322,68 @@ public class ClassWithIgnoredSameType
13221322

13231323
public ClassWithIgnoredSameType(ClassWithIgnoredSameType prop) { }
13241324
}
1325+
1326+
[Fact]
1327+
public void StructWithPropertyInit_DeseralizeEmptyObject()
1328+
{
1329+
string json = @"{}";
1330+
var obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
1331+
Assert.Equal(42, obj.A);
1332+
Assert.Equal(0, obj.B);
1333+
}
1334+
1335+
[Fact]
1336+
public void StructWithPropertyInit_OverrideInitedProperty()
1337+
{
1338+
string json = @"{""A"":43}";
1339+
var obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
1340+
Assert.Equal(43, obj.A);
1341+
Assert.Equal(0, obj.B);
1342+
1343+
json = @"{""A"":0,""B"":44}";
1344+
obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
1345+
Assert.Equal(0, obj.A);
1346+
Assert.Equal(44, obj.B);
1347+
1348+
json = @"{""B"":45}";
1349+
obj = JsonSerializer.Deserialize<StructWithPropertyInit>(json);
1350+
Assert.Equal(42, obj.A); // JSON doesn't set A property so it's expected to be 42
1351+
Assert.Equal(45, obj.B);
1352+
}
1353+
1354+
public struct StructWithPropertyInit
1355+
{
1356+
public long A { get; set; } = 42;
1357+
public long B { get; set; }
1358+
}
1359+
1360+
[Fact]
1361+
public void StructWithFieldInit_DeseralizeEmptyObject()
1362+
{
1363+
string json = @"{}";
1364+
var obj = JsonSerializer.Deserialize<StructWithFieldInit>(json);
1365+
Assert.Equal(0, obj.A);
1366+
Assert.Equal(42, obj.B);
1367+
}
1368+
1369+
public struct StructWithFieldInit
1370+
{
1371+
public long A;
1372+
public long B = 42;
1373+
}
1374+
1375+
[Fact]
1376+
public void StructWithExplicitParameterlessCtor_DeseralizeEmptyObject()
1377+
{
1378+
string json = @"{}";
1379+
var obj = JsonSerializer.Deserialize<StructWithExplicitParameterlessCtor>(json);
1380+
Assert.Equal(42, obj.A);
1381+
}
1382+
1383+
public struct StructWithExplicitParameterlessCtor
1384+
{
1385+
public long A;
1386+
public StructWithExplicitParameterlessCtor() => A = 42;
1387+
}
13251388
}
13261389
}

0 commit comments

Comments
 (0)