title: How to expose a custom generic type as a string in Swagger schema using Swashbuckle.AspNetCore
body: <p>I have a custom generic type that looks roughly like this:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public struct Foo&lt;T&gt;
  {
      public int Value { get; }
      public string Signature { get; }
      public Type Type { get; }
  }
  </code></pre>
  
  <p>This type is is used in request and response bodies and in controller action parameters. Everything is configured so that it's serialized as a string, and it works fine with model binding and JSON serialization. The type has a <code>TypeConverter</code> associated with it, which takes care of converting it to and from a string.</p>
  
  <p>However, the Swagger schema still represents it as an object with 3 properties. The <code>Type</code> property is also expanded, which pulls all the <code>System.Reflection</code> types exposed directly or indirectly by <code>Type</code>.</p>
  
  <p><strong>How can I avoid this and expose my type as a string?</strong></p>
  
  <hr>
  
  <p><strong>First solution attempted: using <code>MapType</code></strong></p>
  
  <p>I tried to use <code>MapType</code>; it works fine if I specify the generic type argument, but doesn't work with the open generic type:</p>
  
  <pre class="lang-cs prettyprint-override"><code>c.MapType(typeof(Foo&lt;Something&gt;), () =&gt; new OpenApiSchema { Type = "string" }); // Works
  c.MapType(typeof(Foo&lt;&gt;), () =&gt; new OpenApiSchema { Type = "string" }); // Doesn't work
  </code></pre>
  
  <p><strong>How can I apply the mapping to <code>Foo&lt;T&gt;</code>, for any <code>T</code>?</strong></p>
  
  <hr>
  
  <p><strong>Current workaround</strong></p>
  
  <p>So far the only workaround I have is pretty ugly :</p>
  
  <pre class="lang-cs prettyprint-override"><code>class SchemaFilter : ISchemaFilter
  {
      public void Apply(OpenApiSchema schema, SchemaFilterContext context)
      {
          if (context.Type is Type type &amp;&amp;
              type.IsGenericType &amp;&amp;
              !type.IsGenericTypeDefinition &amp;&amp;
              type.GetGenericTypeDefinition() == typeof(Foo&lt;&gt;))
          {
              schema.Type = "string";
              schema.Properties.Clear();
          }
          else if (context.Type?.FullName.StartsWith("System.", StringComparison.Ordinal) is true
              &amp;&amp; context.SchemaRepository.TryGetIdFor(context.Type, out var schemaId))
          {
              DocFilter.SchemaIdsToRemove.Add(schemaId);
          }
      }
  }
  
  class DocFilter : IDocumentFilter
  {
      public static readonly HashSet&lt;string&gt; SchemaIdsToRemove = new HashSet&lt;string&gt;();
  
      public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
      {
          foreach (var schemaId in SchemaIdsToRemove)
          {
              swaggerDoc.Components.Schemas.Remove(schemaId);
          }
      }
  }
  </code></pre>