diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Exceptions.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Exceptions.cs index 396357a5e24fce..d268205dce95ee 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Exceptions.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Exceptions.cs @@ -137,129 +137,6 @@ public class Class_ExtData_CtorParam public Class_ExtData_CtorParam(Dictionary extensionData) { } } - [Fact] - public void AnonymousObject() - { - var obj = new { Prop = 5 }; - Type objType = obj.GetType(); - - // 'Prop' property binds with a ctor arg called 'Prop'. - - object newObj = JsonSerializer.Deserialize("{}", objType); - Assert.Equal(0, objType.GetProperty("Prop").GetValue(newObj)); - - newObj = JsonSerializer.Deserialize(@"{""Prop"":5}", objType); - Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj)); - } - - [Fact] - public void AnonymousObject_NamingPolicy() - { - const string Json = @"{""prop"":5}"; - - var obj = new { Prop = 5 }; - Type objType = obj.GetType(); - - // 'Prop' property binds with a ctor arg called 'Prop'. - - object newObj = JsonSerializer.Deserialize(Json, objType); - // Verify no match if no naming policy - Assert.Equal(0, objType.GetProperty("Prop").GetValue(newObj)); - - var options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - - newObj = JsonSerializer.Deserialize(Json, objType, options); - // Verify match with naming policy - Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj)); - } - -#if NETCOREAPP // These require the C# 9.0 "record" feature which is not available for all TFMs. - private record MyRecord(int Prop); - - [Fact] - public void Record() - { - // 'Prop' property binds with a ctor arg called 'Prop'. - MyRecord obj = JsonSerializer.Deserialize("{}"); - Assert.Equal(0, obj.Prop); - - obj = JsonSerializer.Deserialize(@"{""Prop"":5}"); - Assert.Equal(5, obj.Prop); - } - - public record AgeRecord(int age) - { - public string Age { get; set; } = age.ToString(); - } - - [Fact] - public void RecordWithSamePropertyNameDifferentTypes() - { - AgeRecord obj = JsonSerializer.Deserialize(@"{""age"":1}"); - Assert.Equal(1, obj.age); - } - - private record MyRecordWithUnboundCtorProperty(int IntProp1, int IntProp2) - { - public string StringProp { get; set; } - } - - [Fact] - public void RecordWithAdditionalProperty() - { - MyRecordWithUnboundCtorProperty obj = JsonSerializer.Deserialize( - @"{""IntProp1"":1,""IntProp2"":2,""StringProp"":""hello""}"); - - Assert.Equal(1, obj.IntProp1); - Assert.Equal(2, obj.IntProp2); - - // StringProp is not bound to any constructor property. - Assert.Equal("hello", obj.StringProp); - } - - [Fact] - public void Record_NamingPolicy() - { - const string Json = @"{""prop"":5}"; - - // 'Prop' property binds with a ctor arg called 'Prop'. - - // Verify no match if no naming policy - MyRecord obj = JsonSerializer.Deserialize(Json); - Assert.Equal(0, obj.Prop); - - var options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - - // Verify match with naming policy - obj = JsonSerializer.Deserialize(Json, options); - Assert.Equal(5, obj.Prop); - } -#endif - - [Fact] - public void PocoWithSamePropertyNameDifferentTypes() - { - AgePoco obj = JsonSerializer.Deserialize(@"{""age"":1}"); - Assert.Equal(1, obj.age); - } - - private class AgePoco - { - public AgePoco(int age) - { - this.age = age; - } - public int age { get; set; } - - public string Age { get; set; } - } - [Fact] public async Task DeserializePathForObjectFails() { diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs index 7cf574598d7e3f..b3315fc8871100 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -1013,5 +1013,126 @@ public async Task InvalidJsonFails() await Assert.ThrowsAsync(() => Serializer.DeserializeWrapper("{x")); await Assert.ThrowsAsync(() => Serializer.DeserializeWrapper("{true")); } + + [Fact] + public void AnonymousObject() + { + var obj = new { Prop = 5 }; + Type objType = obj.GetType(); + + // 'Prop' property binds with a ctor arg called 'Prop'. + + object newObj = JsonSerializer.Deserialize("{}", objType); + Assert.Equal(0, objType.GetProperty("Prop").GetValue(newObj)); + + newObj = JsonSerializer.Deserialize(@"{""Prop"":5}", objType); + Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj)); + } + + [Fact] + public void AnonymousObject_NamingPolicy() + { + const string Json = @"{""prop"":5}"; + + var obj = new { Prop = 5 }; + Type objType = obj.GetType(); + + // 'Prop' property binds with a ctor arg called 'Prop'. + + object newObj = JsonSerializer.Deserialize(Json, objType); + // Verify no match if no naming policy + Assert.Equal(0, objType.GetProperty("Prop").GetValue(newObj)); + + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + newObj = JsonSerializer.Deserialize(Json, objType, options); + // Verify match with naming policy + Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj)); + } + + private record MyRecord(int Prop); + + [Fact] + public void Record() + { + // 'Prop' property binds with a ctor arg called 'Prop'. + MyRecord obj = JsonSerializer.Deserialize("{}"); + Assert.Equal(0, obj.Prop); + + obj = JsonSerializer.Deserialize(@"{""Prop"":5}"); + Assert.Equal(5, obj.Prop); + } + + private record AgeRecord(int age) + { + public string Age { get; set; } = age.ToString(); + } + + [Fact] + public void RecordWithSamePropertyNameDifferentTypes() + { + AgeRecord obj = JsonSerializer.Deserialize(@"{""age"":1}"); + Assert.Equal(1, obj.age); + } + + private record MyRecordWithUnboundCtorProperty(int IntProp1, int IntProp2) + { + public string StringProp { get; set; } + } + + [Fact] + public void RecordWithAdditionalProperty() + { + MyRecordWithUnboundCtorProperty obj = JsonSerializer.Deserialize( + @"{""IntProp1"":1,""IntProp2"":2,""StringProp"":""hello""}"); + + Assert.Equal(1, obj.IntProp1); + Assert.Equal(2, obj.IntProp2); + + // StringProp is not bound to any constructor property. + Assert.Equal("hello", obj.StringProp); + } + + [Fact] + public void Record_NamingPolicy() + { + const string Json = @"{""prop"":5}"; + + // 'Prop' property binds with a ctor arg called 'Prop'. + + // Verify no match if no naming policy + MyRecord obj = JsonSerializer.Deserialize(Json); + Assert.Equal(0, obj.Prop); + + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + // Verify match with naming policy + obj = JsonSerializer.Deserialize(Json, options); + Assert.Equal(5, obj.Prop); + } + + private class AgePoco + { + public AgePoco(int age) + { + this.age = age; + } + + public int age { get; set; } + public string Age { get; set; } + } + + [Fact] + public void PocoWithSamePropertyNameDifferentTypes() + { + AgePoco obj = JsonSerializer.Deserialize(@"{""age"":1}"); + Assert.Equal(1, obj.age); + } } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/IsExternalInit.cs b/src/libraries/System.Text.Json/tests/Serialization/IsExternalInit.cs new file mode 100644 index 00000000000000..d789ecb6e2a185 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/Serialization/IsExternalInit.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Runtime.CompilerServices +{ + /// + /// Dummy class so C# 'Record' types can compile on NetStandard and NetFx. + /// + public sealed class IsExternalInit { } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj index 7701738f903180..72f5dbc5097b3f 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -142,6 +142,9 @@ + + +