Home > database >  .NET swagger leave out property from example value
.NET swagger leave out property from example value

Time:10-08

Is there a way to exclude/remove properties from your example value?

I'm using XML comments on my models to provide information on the swagger page with c.IncludeXmlComments I use the ///<example>Example Value</example> XML tag to set the example values. My request model does not require all the fields to be set by default, but if I don't set an example XML tag the example value is translated to it's type. Looking like this

{
  "ID": "string",
  "ExampleSetValue": "Example Value"
}

And I want my example value to only contain the ExampleSetValue property so my example value looks like this

{
  "ExampleSetValue": "Example Value"
}

This is the swagger setup in my startup

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", openApiInfo);
    c.AddSecurityDefinition("Bearer", openApiSecurityScheme);
    c.AddSecurityRequirement(openApiSecurityRequirement);

    // Set the comments path for the Swagger JSON and UI.
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);

    c.IncludeXmlComments(xmlPath);
});

My Request Model

public class CreateRequest
{
        /// <summary>
        /// ID of the user if available
        /// </summary>
        public string ID { get; set; }
        /// <summary>
        /// ExampleSetValue
        /// </summary>
        /// <example>Example Value</example>
        public string ExampleSetValue { get; set; }
    }

CodePudding user response:

Xml comment seems cannot be used to exclude the property.

If you want to ignore the property, I suggest you use the [System.Text.Json.Serialization.JsonIgnore] attribute. But in this way it will also make your property hidden when you serialize or deserialize the data.

public class CreateRequest
{
    /// <summary>
    /// ID of the user if available
    /// </summary>
    [JsonIgnore]                   //add this..........
    public string ID { get; set; }
    /// <summary>
    /// ExampleSetValue
    /// </summary>
    /// <example>Example Value</example>
    public string ExampleSetValue { get; set; }
}

If you only want to exclude the property from example value, you need custom ISchemaFilter:

Model:

public class CreateRequest
{
    /// <summary>
    /// ID of the user if available
    /// </summary>
    [IgnoreDataMember]               //add this..........
    public string ID { get; set; }
    /// <summary>
    /// ExampleSetValue
    /// </summary>
    /// <example>Example Value</example>
    public string ExampleSetValue { get; set; }
}

Custom ISchemaFilter:

public class MySwaggerSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (schema?.Properties == null)
        {
            return;
        }
        var ignoreDataMemberProperties = context.Type.GetProperties()
            .Where(t => t.GetCustomAttribute<IgnoreDataMemberAttribute>() != null);

        foreach (var ignoreDataMemberProperty in ignoreDataMemberProperties)
        {
            var propertyToHide = schema.Properties.Keys
                .SingleOrDefault(x => x.ToLower() == ignoreDataMemberProperty.Name.ToLower());

            if (propertyToHide != null)
            {
                schema.Properties.Remove(propertyToHide);
            }
        }
    }
}

Register the filter:

services.AddSwaggerGen(c =>
{
    //......
    c.SchemaFilter<MySwaggerSchemaFilter>();
});

CodePudding user response:

I found a different approach which suited my case exactly how I wanted. You can set an example object on your schema which is of type OpenApiObject.

I Created a Document filter to which loops over the schemas in my swagger.

public class AddExamplesFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        foreach (var schema in context.SchemaRepository.Schemas)
        {
            schema.Value.Example = ExampleManager.GetExample(schema.Key);
        }
    }
}

Created the ExampleManager class which returns the example object I want according to the schema name.

public static OpenApiObject GetExample(string requestModelName)
{
    return requestModelName switch
    {
        "ObjectExample" => ObjectExample.GetExample(),
        _ =>  null
    };
}

And as the final step created an example class which corresponds exactly on how I want my example to look like. Where I used the OpenApiObject class

public static class ObjectExample
{
    public static OpenApiObject GetExample()
    {
        return new OpenApiObject
        {
            ["ObjectInsideObject"] = new OpenApiObject
            {
                ["Name"] = new OpenApiString("name"),
            },
            ["ArrayWithObjects"] = new OpenApiArray
            {
                new OpenApiObject
                {
                    ["Object"] = new OpenApiObject
                    {
                        ["integer"] = new OpenApiInteger(15),
                    },
                    ["Description"] = new OpenApiString("description")
                }
            },
            ["date"] = new OpenApiDate(new DateTime().AddMonths(1)),
            ["Description"] = new OpenApiString("description"),
        };
    }
}

Final look on Swagger page Swagger page

  • Related