Skip to content

Commit

Permalink
Add JsonSchemaExporterContext.ParentTypeInfo (dotnet#104550)
Browse files Browse the repository at this point in the history
  • Loading branch information
eiriktsarpalis authored Jul 9, 2024
1 parent 0dd2a62 commit 7f5ce1e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/libraries/System.Text.Json/ref/System.Text.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,7 @@ public readonly partial struct JsonSchemaExporterContext
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public System.Text.Json.Serialization.Metadata.JsonTypeInfo? BaseTypeInfo { get { throw null; } }
public System.Text.Json.Serialization.Metadata.JsonPropertyInfo? PropertyInfo { get { throw null; } }
public System.ReadOnlySpan<string> Path { get { throw null; } }
public System.Text.Json.Serialization.Metadata.JsonTypeInfo TypeInfo { get { throw null; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private static JsonSchema MapJsonSchemaCore(
JsonPropertyInfo? propertyInfo = null,
JsonConverter? customConverter = null,
JsonNumberHandling? customNumberHandling = null,
Type? parentPolymorphicType = null,
JsonTypeInfo? parentPolymorphicTypeInfo = null,
bool parentPolymorphicTypeContainsTypesWithoutDiscriminator = false,
bool parentPolymorphicTypeIsNonNullable = false,
KeyValuePair<string, JsonSchema>? typeDiscriminator = null,
Expand All @@ -90,7 +90,7 @@ private static JsonSchema MapJsonSchemaCore(
return CompleteSchema(ref state, schema);
}

if (parentPolymorphicType is null && typeInfo.PolymorphismOptions is { DerivedTypes.Count: > 0 } polyOptions)
if (parentPolymorphicTypeInfo is null && typeInfo.PolymorphismOptions is { DerivedTypes.Count: > 0 } polyOptions)
{
// This is the base type of a polymorphic type hierarchy. The schema for this type
// will include an "anyOf" property with the schemas for all derived types.
Expand Down Expand Up @@ -133,7 +133,7 @@ private static JsonSchema MapJsonSchemaCore(
JsonSchema derivedSchema = MapJsonSchemaCore(
ref state,
derivedTypeInfo,
parentPolymorphicType: typeInfo.Type,
parentPolymorphicTypeInfo: typeInfo,
typeDiscriminator: derivedTypeDiscriminator,
parentPolymorphicTypeContainsTypesWithoutDiscriminator: containsTypesWithoutDiscriminator,
parentPolymorphicTypeIsNonNullable: propertyInfo is { IsGetNullable: false, IsSetNullable: false },
Expand Down Expand Up @@ -372,7 +372,7 @@ JsonSchema CompleteSchema(ref GenerationState state, JsonSchema schema)
if (state.ExporterOptions.TransformSchemaNode != null)
{
// Prime the schema for invocation by the JsonNode transformer.
schema.ExporterContext = state.CreateContext(typeInfo, propertyInfo);
schema.ExporterContext = state.CreateContext(typeInfo, propertyInfo, parentPolymorphicTypeInfo);
}

return schema;
Expand Down Expand Up @@ -454,9 +454,9 @@ public void PopGeneratedType()
_generationStack.RemoveAt(_generationStack.Count - 1);
}

public JsonSchemaExporterContext CreateContext(JsonTypeInfo typeInfo, JsonPropertyInfo? propertyInfo)
public JsonSchemaExporterContext CreateContext(JsonTypeInfo typeInfo, JsonPropertyInfo? propertyInfo, JsonTypeInfo? baseTypeInfo)
{
return new JsonSchemaExporterContext(typeInfo, propertyInfo, _currentPath.ToArray());
return new JsonSchemaExporterContext(typeInfo, propertyInfo, baseTypeInfo, _currentPath.ToArray());
}

private static string FormatJsonPointer(List<string> currentPathList, int depth)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ public readonly struct JsonSchemaExporterContext
{
private readonly string[] _path;

internal JsonSchemaExporterContext(JsonTypeInfo typeInfo, JsonPropertyInfo? propertyInfo, string[] path)
internal JsonSchemaExporterContext(
JsonTypeInfo typeInfo,
JsonPropertyInfo? propertyInfo,
JsonTypeInfo? baseTypeInfo,
string[] path)
{
TypeInfo = typeInfo;
PropertyInfo = propertyInfo;
BaseTypeInfo = baseTypeInfo;
_path = path;
}

Expand All @@ -29,6 +34,11 @@ internal JsonSchemaExporterContext(JsonTypeInfo typeInfo, JsonPropertyInfo? prop
/// </summary>
public JsonPropertyInfo? PropertyInfo { get; }

/// <summary>
/// Gets the <see cref="JsonTypeInfo"/> for polymorphic base type if the schema is being generated for a derived type.
/// </summary>
public JsonTypeInfo? BaseTypeInfo { get; }

/// <summary>
/// The path to the current node in the generated JSON schema.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,39 @@ public void JsonSerializerOptions_SmallMaxDepth_ThrowsInvalidOperationException(
Assert.Contains("depth", ex.Message);
}

[Theory]
[InlineData(typeof(int))]
[InlineData(typeof(string))]
[InlineData(typeof(SimplePoco))]
[InlineData(typeof(DiscriminatedUnion))]
public void JsonSchemaExporterContext_BaseTypeInfo_ReturnsExpectedValue(Type type)
{
bool isCallbackInvoked = false;
JsonSerializerOptions options = Serializer.DefaultOptions;
JsonSchemaExporterOptions exporterOptions = new()
{
TransformSchemaNode = (ctx, node) =>
{
if (typeof(DiscriminatedUnion).IsAssignableFrom(ctx.TypeInfo.Type) &&
typeof(DiscriminatedUnion) != ctx.TypeInfo.Type)
{
Assert.NotNull(ctx.BaseTypeInfo);
Assert.Equal(typeof(DiscriminatedUnion), ctx.BaseTypeInfo.Type);
}
else
{
Assert.Null(ctx.BaseTypeInfo);
}
isCallbackInvoked = true;
return node;
}
};

options.GetJsonSchemaAsNode(type, exporterOptions);
Assert.True(isCallbackInvoked);
}

[Fact]
public void ReferenceHandlePreserve_Enabled_ThrowsNotSupportedException()
{
Expand Down

0 comments on commit 7f5ce1e

Please sign in to comment.