diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Schema/JsonSchemaExporter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Schema/JsonSchemaExporter.cs index 00c39aa3ef2821..9126b2a581a8d7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Schema/JsonSchemaExporter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Schema/JsonSchemaExporter.cs @@ -447,7 +447,8 @@ bool IsNullableSchema(JsonSchemaExporterOptions options) if (propertyInfo is not null) { - return propertyInfo.IsGetNullable || propertyInfo.IsSetNullable; + return (propertyInfo.Get is not null && propertyInfo.IsGetNullable) || + (propertyInfo.Set is not null && propertyInfo.IsSetNullable); } if (typeInfo.IsNullable) diff --git a/src/libraries/System.Text.Json/tests/Common/JsonSchemaExporterTests.cs b/src/libraries/System.Text.Json/tests/Common/JsonSchemaExporterTests.cs index 190166ef19c3f8..8355e80f3637e8 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonSchemaExporterTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonSchemaExporterTests.cs @@ -82,6 +82,30 @@ public void TreatNullObliviousAsNonNullable_True_MarksReferenceTypesAsNonNullabl Assert.Equal(expectedType, (string)schema["type"]!); } + [Fact] + public void GetOnlyProperties_DoNotUseSetterNullabilityInSchema() + { + JsonNode schema = Serializer.DefaultOptions.GetJsonSchemaAsNode(typeof(PocoWithGetOnlyProperties)); + const string ExpectedJsonSchema = """ + { + "type": ["object", "null"], + "properties": { + "Values": { + "type": "array", + "items": { "type": ["string", "null"] } + }, + "SingleValueGetOnly": { "type": "string" }, + "NullableGetOnly": { "type": ["string", "null"] }, + "SingleValueGetSet": { "type": "string" }, + "NonNullableReadonlyField": { "type": "string" }, + "NullableReadonlyField": { "type": ["string", "null"] } + } + } + """; + + AssertValidJsonSchema(typeof(PocoWithGetOnlyProperties), ExpectedJsonSchema, schema); + } + [Theory] [InlineData(typeof(Type))] [InlineData(typeof(MethodInfo))] @@ -262,6 +286,21 @@ public void LegacySchemaExporter_CanAccessReflectedMembers() record PocoWithProperty(int Value); + sealed class PocoWithGetOnlyProperties + { + public IEnumerable Values => []; + public string SingleValueGetOnly { get; } = "value"; + public string? NullableGetOnly { get; } + public string SingleValueGetSet { get; set; } = "value"; + [JsonInclude] + public readonly string NonNullableReadonlyField = "value"; + +#pragma warning disable CS0649 // field never assigned to + [JsonInclude] + public readonly string? NullableReadonlyField; +#pragma warning restore CS0649 + } + [JsonSerializable(typeof(PocoWithProperty))] partial class PocoWithPropertyContext : JsonSerializerContext;