diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs index 4357b7dac9198b..0827931b5df1de 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitMemberAccessor.cs @@ -49,6 +49,11 @@ internal sealed class ReflectionEmitMemberAccessor : MemberAccessor else { generator.Emit(OpCodes.Newobj, realMethod); + if (type.IsValueType) + { + // Since C# 10 it's now possible to have parameterless constructors in structs + generator.Emit(OpCodes.Box, type); + } } generator.Emit(OpCodes.Ret); diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs index 93aff74c1b4d0b..53a89e92028ece 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -1322,5 +1322,68 @@ public class ClassWithIgnoredSameType public ClassWithIgnoredSameType(ClassWithIgnoredSameType prop) { } } + + [Fact] + public void StructWithPropertyInit_DeseralizeEmptyObject() + { + string json = @"{}"; + var obj = JsonSerializer.Deserialize(json); + Assert.Equal(42, obj.A); + Assert.Equal(0, obj.B); + } + + [Fact] + public void StructWithPropertyInit_OverrideInitedProperty() + { + string json = @"{""A"":43}"; + var obj = JsonSerializer.Deserialize(json); + Assert.Equal(43, obj.A); + Assert.Equal(0, obj.B); + + json = @"{""A"":0,""B"":44}"; + obj = JsonSerializer.Deserialize(json); + Assert.Equal(0, obj.A); + Assert.Equal(44, obj.B); + + json = @"{""B"":45}"; + obj = JsonSerializer.Deserialize(json); + Assert.Equal(42, obj.A); // JSON doesn't set A property so it's expected to be 42 + Assert.Equal(45, obj.B); + } + + public struct StructWithPropertyInit + { + public long A { get; set; } = 42; + public long B { get; set; } + } + + [Fact] + public void StructWithFieldInit_DeseralizeEmptyObject() + { + string json = @"{}"; + var obj = JsonSerializer.Deserialize(json); + Assert.Equal(0, obj.A); + Assert.Equal(42, obj.B); + } + + public struct StructWithFieldInit + { + public long A; + public long B = 42; + } + + [Fact] + public void StructWithExplicitParameterlessCtor_DeseralizeEmptyObject() + { + string json = @"{}"; + var obj = JsonSerializer.Deserialize(json); + Assert.Equal(42, obj.A); + } + + public struct StructWithExplicitParameterlessCtor + { + public long A; + public StructWithExplicitParameterlessCtor() => A = 42; + } } }