Skip to content

Commit 79795eb

Browse files
eiriktsarpalismikelle-rogers
authored andcommitted
Fix transformer handling of boolean schemas in JsonSchemaExporter. (dotnet#109954)
* Fix transformer handling of boolean schemas in JsonSchemaExporter. * Address feedback.
1 parent 9d96e37 commit 79795eb

File tree

11 files changed

+73
-11
lines changed

11 files changed

+73
-11
lines changed

src/libraries/System.Text.Json/src/System/Text/Json/Schema/JsonSchema.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ internal sealed class JsonSchema
2626
internal const string MinLengthPropertyName = "minLength";
2727
internal const string MaxLengthPropertyName = "maxLength";
2828

29-
public static JsonSchema False { get; } = new(false);
30-
public static JsonSchema True { get; } = new(true);
29+
public static JsonSchema CreateFalseSchema() => new(false);
30+
public static JsonSchema CreateTrueSchema() => new(true);
3131

3232
public JsonSchema() { }
3333
private JsonSchema(bool trueOrFalse) { _trueOrFalse = trueOrFalse; }
@@ -279,7 +279,7 @@ public static void EnsureMutable(ref JsonSchema schema)
279279
switch (schema._trueOrFalse)
280280
{
281281
case false:
282-
schema = new JsonSchema { Not = True };
282+
schema = new JsonSchema { Not = CreateTrueSchema() };
283283
break;
284284
case true:
285285
schema = new JsonSchema();

src/libraries/System.Text.Json/src/System/Text/Json/Schema/JsonSchemaExporter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ private static JsonSchema MapJsonSchemaCore(
211211
JsonUnmappedMemberHandling effectiveUnmappedMemberHandling = typeInfo.UnmappedMemberHandling ?? typeInfo.Options.UnmappedMemberHandling;
212212
if (effectiveUnmappedMemberHandling is JsonUnmappedMemberHandling.Disallow)
213213
{
214-
additionalProperties = JsonSchema.False;
214+
additionalProperties = JsonSchema.CreateFalseSchema();
215215
}
216216

217217
if (typeDiscriminator is { } typeDiscriminatorPair)
@@ -350,7 +350,7 @@ private static JsonSchema MapJsonSchemaCore(
350350
default:
351351
Debug.Assert(typeInfo.Kind is JsonTypeInfoKind.None);
352352
// Return a `true` schema for types with user-defined converters.
353-
return CompleteSchema(ref state, JsonSchema.True);
353+
return CompleteSchema(ref state, JsonSchema.CreateTrueSchema());
354354
}
355355

356356
JsonSchema CompleteSchema(ref GenerationState state, JsonSchema schema)

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,6 @@ public override void Write(Utf8JsonWriter writer, JsonNode? value, JsonSerialize
8080
return node;
8181
}
8282

83-
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.True;
83+
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.CreateTrueSchema();
8484
}
8585
}

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonValueConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ public override void Write(Utf8JsonWriter writer, JsonValue? value, JsonSerializ
3131
return JsonValue.CreateFromElement(ref element, options.GetNodeOptions());
3232
}
3333

34-
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.True;
34+
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.CreateTrueSchema();
3535
}
3636
}

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,6 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert,
147147
return true;
148148
}
149149

150-
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.True;
150+
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.CreateTrueSchema();
151151
}
152152
}

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/JsonDocumentConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ public override void Write(Utf8JsonWriter writer, JsonDocument? value, JsonSeria
2626
value.WriteTo(writer);
2727
}
2828

29-
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.True;
29+
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.CreateTrueSchema();
3030
}
3131
}

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/JsonElementConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ public override void Write(Utf8JsonWriter writer, JsonElement value, JsonSeriali
1818
value.WriteTo(writer);
1919
}
2020

21-
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.True;
21+
internal override JsonSchema? GetSchema(JsonNumberHandling _) => JsonSchema.CreateTrueSchema();
2222
}
2323
}

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions
2121
throw new NotSupportedException(ErrorMessage);
2222

2323
internal override JsonSchema? GetSchema(JsonNumberHandling _) =>
24-
new JsonSchema { Comment = "Unsupported .NET type", Not = JsonSchema.True };
24+
new JsonSchema { Comment = "Unsupported .NET type", Not = JsonSchema.CreateTrueSchema() };
2525
}
2626
}

src/libraries/System.Text.Json/tests/Common/JsonSchemaExporterTests.TestTypes.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,18 @@ of the type which points to the first occurrence. */
11021102
}
11031103
""");
11041104

1105+
yield return new TestData<ClassWithPropertiesUsingCustomConverters>(
1106+
Value: new() { Prop1 = new() , Prop2 = new() },
1107+
ExpectedJsonSchema: """
1108+
{
1109+
"type": ["object","null"],
1110+
"properties": {
1111+
"Prop1": true,
1112+
"Prop2": true,
1113+
}
1114+
}
1115+
""");
1116+
11051117
// Collection types
11061118
yield return new TestData<int[]>([1, 2, 3], ExpectedJsonSchema: """{"type":["array","null"],"items":{"type":"integer"}}""");
11071119
yield return new TestData<List<bool>>([false, true, false], ExpectedJsonSchema: """{"type":["array","null"],"items":{"type":"boolean"}}""");
@@ -1586,6 +1598,29 @@ public interface ITestData
15861598
IEnumerable<ITestData> GetTestDataForAllValues();
15871599
}
15881600

1601+
public class ClassWithPropertiesUsingCustomConverters
1602+
{
1603+
[JsonPropertyOrder(0)]
1604+
public ClassWithCustomConverter1 Prop1 { get; set; }
1605+
[JsonPropertyOrder(1)]
1606+
public ClassWithCustomConverter2 Prop2 { get; set; }
1607+
1608+
[JsonConverter(typeof(CustomConverter<ClassWithCustomConverter1>))]
1609+
public class ClassWithCustomConverter1;
1610+
1611+
[JsonConverter(typeof(CustomConverter<ClassWithCustomConverter2>))]
1612+
public class ClassWithCustomConverter2;
1613+
1614+
public sealed class CustomConverter<T> : JsonConverter<T>
1615+
{
1616+
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
1617+
=> default;
1618+
1619+
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
1620+
=> writer.WriteNullValue();
1621+
}
1622+
}
1623+
15891624
private static TAttribute? GetCustomAttribute<TAttribute>(ICustomAttributeProvider? provider, bool inherit = false) where TAttribute : Attribute
15901625
=> provider?.GetCustomAttributes(typeof(TAttribute), inherit).FirstOrDefault() as TAttribute;
15911626
}

src/libraries/System.Text.Json/tests/Common/JsonSchemaExporterTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,32 @@ public void CanGenerateXElementSchema()
9898
Assert.True(schema.ToJsonString().Length < 100_000);
9999
}
100100

101+
[Fact]
102+
public void TransformSchemaNode_PropertiesWithCustomConverters()
103+
{
104+
// Regression test for https://github.com/dotnet/runtime/issues/109868
105+
List<(Type? ParentType, string? PropertyName, Type type)> visitedNodes = new();
106+
JsonSchemaExporterOptions exporterOptions = new()
107+
{
108+
TransformSchemaNode = (ctx, schema) =>
109+
{
110+
visitedNodes.Add((ctx.PropertyInfo?.DeclaringType, ctx.PropertyInfo?.Name, ctx.TypeInfo.Type));
111+
return schema;
112+
}
113+
};
114+
115+
List<(Type? ParentType, string? PropertyName, Type type)> expectedNodes =
116+
[
117+
(typeof(ClassWithPropertiesUsingCustomConverters), "Prop1", typeof(ClassWithPropertiesUsingCustomConverters.ClassWithCustomConverter1)),
118+
(typeof(ClassWithPropertiesUsingCustomConverters), "Prop2", typeof(ClassWithPropertiesUsingCustomConverters.ClassWithCustomConverter2)),
119+
(null, null, typeof(ClassWithPropertiesUsingCustomConverters)),
120+
];
121+
122+
Serializer.DefaultOptions.GetJsonSchemaAsNode(typeof(ClassWithPropertiesUsingCustomConverters), exporterOptions);
123+
124+
Assert.Equal(expectedNodes, visitedNodes);
125+
}
126+
101127
[Fact]
102128
public void TypeWithDisallowUnmappedMembers_AdditionalPropertiesFailValidation()
103129
{

0 commit comments

Comments
 (0)