Last active
December 12, 2025 21:40
-
-
Save SteffenBlake/67c4c7a8b517ff26d68e8694168cdbce to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// <summary> | |
| /// Automatically detects dotVariant union types and properly re-schemas | |
| /// them to instead be registered with oneOf OpenApi spec | |
| /// </summary> | |
| public class DotVariantSchemaTransformer : IOpenApiSchemaTransformer | |
| { | |
| public async Task TransformAsync( | |
| OpenApiSchema schema, | |
| OpenApiSchemaTransformerContext context, | |
| CancellationToken cancellationToken | |
| ) | |
| { | |
| // Step one: confirm it is a public class | |
| var type = context.JsonTypeInfo.Type; | |
| if (!type.IsClass || !type.IsPublic) | |
| { | |
| return; | |
| } | |
| // Step 2: It should have a void Visit(...) function | |
| var visit = type.GetMethods(BindingFlags.Public | BindingFlags.Instance) | |
| .FirstOrDefault(m => | |
| m.Name == "Visit" && | |
| !m.IsGenericMethod && | |
| m.ReturnType == typeof(void) | |
| ); | |
| if (visit == null) | |
| { | |
| return; | |
| } | |
| var unionTypes = new HashSet<Type>(); | |
| // Step 3: all params of the visit function should be Action<SomeType> | |
| // Extract out all those SomeTypes | |
| foreach (var p in visit.GetParameters()) | |
| { | |
| if (!p.ParameterType.IsGenericType) | |
| { | |
| return; | |
| } | |
| var def = p.ParameterType.GetGenericTypeDefinition(); | |
| if (def != typeof(Action<>)) | |
| { | |
| return; | |
| } | |
| var unionType = p.ParameterType.GetGenericArguments()[0]; | |
| unionTypes.Add(unionType); | |
| } | |
| // Step 4: clear out the non-exposed properties that show up defaul | |
| // on a dotVariant type (IsEmpty, Index) | |
| schema.Properties = null; | |
| // Step 5: Convert all the extracted types and register them as OneOfs | |
| schema.OneOf = []; | |
| foreach(var unionType in unionTypes) | |
| { | |
| schema.OneOf.Add( | |
| await context.GetOrCreateSchemaAsync( | |
| unionType, cancellationToken: cancellationToken | |
| ) | |
| ); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment