Skip to content

Commit

Permalink
.Net: Update JsonSchemaMapper to incorporate the .NET 9 shim (#7960)
Browse files Browse the repository at this point in the history
Updates `JsonSchemaMapper` to include the changes from
eiriktsarpalis/stj-schema-mapper#5. The changes
reimplement the component as a shim over the built-in schema exporter
available in System.Text.Json v9, for targets that support it. This
should give SK built-in schema generation for free simply by upgrading
its dependencies to STJ version 9.0.x once generally available.

cc @stephentoub @markwallace-microsoft

---------

Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
  • Loading branch information
eiriktsarpalis and markwallace-microsoft committed Sep 2, 2024
1 parent 78289af commit 38a2c26
Show file tree
Hide file tree
Showing 10 changed files with 2,026 additions and 1,168 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization.Metadata;

namespace JsonSchemaMapper;

/// <summary>
/// Defines the context in which a JSON schema within a type graph is being generated.
/// </summary>
#if EXPOSE_JSON_SCHEMA_MAPPER
public
#else
internal
#endif
readonly struct JsonSchemaGenerationContext
{
internal JsonSchemaGenerationContext(
JsonTypeInfo typeInfo,
Type? declaringType,
JsonPropertyInfo? propertyInfo,
ParameterInfo? parameterInfo,
ICustomAttributeProvider? propertyAttributeProvider)
{
TypeInfo = typeInfo;
DeclaringType = declaringType;
PropertyInfo = propertyInfo;
ParameterInfo = parameterInfo;
PropertyAttributeProvider = propertyAttributeProvider;
}

/// <summary>
/// The <see cref="JsonTypeInfo"/> for the type being processed.
/// </summary>
public JsonTypeInfo TypeInfo { get; }

/// <summary>
/// The declaring type of the property or parameter being processed.
/// </summary>
public Type? DeclaringType { get; }

/// <summary>
/// The <see cref="JsonPropertyInfo"/> if the schema is being generated for a property.
/// </summary>
public JsonPropertyInfo? PropertyInfo { get; }

/// <summary>
/// The <see cref="System.Reflection.ParameterInfo"/> if a constructor parameter
/// has been associated with the accompanying <see cref="PropertyInfo"/>.
/// </summary>
public ParameterInfo? ParameterInfo { get; }

/// <summary>
/// The <see cref="ICustomAttributeProvider"/> corresponding to the property or field being processed.
/// </summary>
public ICustomAttributeProvider? PropertyAttributeProvider { get; }

/// <summary>
/// Checks if the type, property, or parameter has the specified attribute applied.
/// </summary>
/// <typeparam name="TAttribute">The type of the attribute to resolve.</typeparam>
/// <param name="inherit">Whether to look up the hierarchy chain for the inherited custom attribute.</param>
/// <returns>True if the attribute is defined by the current context.</returns>
public bool IsDefined<TAttribute>(bool inherit = false)
where TAttribute : Attribute =>
GetCustomAttributes(typeof(TAttribute), inherit).Any();

/// <summary>
/// Checks if the type, property, or parameter has the specified attribute applied.
/// </summary>
/// <typeparam name="TAttribute">The type of the attribute to resolve.</typeparam>
/// <param name="inherit">Whether to look up the hierarchy chain for the inherited custom attribute.</param>
/// <returns>The first attribute resolved from the current context, or null.</returns>
public TAttribute? GetAttribute<TAttribute>(bool inherit = false)
where TAttribute : Attribute =>
(TAttribute?)GetCustomAttributes(typeof(TAttribute), inherit).FirstOrDefault();

/// <summary>
/// Resolves any custom attributes that might have been applied to the type, property, or parameter.
/// </summary>
/// <param name="type">The attribute type to resolve.</param>
/// <param name="inherit">Whether to look up the hierarchy chain for the inherited custom attribute.</param>
/// <returns>An enumerable of all custom attributes defined by the context.</returns>
public IEnumerable<Attribute> GetCustomAttributes(Type type, bool inherit = false)
{
// Resolves attributes starting from the property, then the parameter, and finally the type itself.
return GetAttrs(PropertyAttributeProvider)
.Concat(GetAttrs(ParameterInfo))
.Concat(GetAttrs(TypeInfo.Type))
.Cast<Attribute>();

object[] GetAttrs(ICustomAttributeProvider? provider) =>
provider?.GetCustomAttributes(type, inherit) ?? Array.Empty<object>();
}
}
Loading

0 comments on commit 38a2c26

Please sign in to comment.