Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to hide property from displaying in Swagger? #1230

Closed
syaifulnizamyahya opened this issue Mar 29, 2018 · 52 comments
Closed

How to hide property from displaying in Swagger? #1230

syaifulnizamyahya opened this issue Mar 29, 2018 · 52 comments

Comments

@syaifulnizamyahya
Copy link

I have a property that I want to serialize but dont want it visible in Swagger.

Example.
public long Id { get; set; }

Things I tried

  1. Internal - doesnt work because i need to access the property somewhere.
  2. These decorator [IgnoreDataMember], [JsonIgnore], [XmlIgnore] - doesnt work. I need the property to be serializable.

Any help?

Thanks.

@yahyanajar
Copy link

cf. https://stackoverflow.com/questions/41005730/how-to-configure-swashbuckle-to-ignore-property-on-model

@arlan85
Copy link

arlan85 commented Oct 4, 2018

@yahyanajar It doesn't work. It still show ignored properties with [JsonIgnore] in request model on get actions.
@syaifulnizamyahya did you resolve this issue?

@Sandeep321
Copy link

    [JsonIgnore]
    internal string CountryCode { get; set; }

This works for me.

@Calx-Takeno
Copy link

JsonIgnore doesn't work for me

@Sandeep321
Copy link

Use the [DataContract] for the model and use [DataMember] for the properties which you want to show in Swagger. Any property which isn't marked as [DataMember] doesn't show up in your swagger definition. Let me know if this works or not.

@olicooper
Copy link

None of the methods above work for me. I am using .NET Core 2.2.

  • [DataContract] ends up showing all members anyway
  • marking attribute as 'internal' or [JsonIgnore] doesn't deserialize the property if manually added in swaggerUI

@bverb
Copy link

bverb commented Jul 10, 2019

I've solved this issue before. You can create a custom attribute, then make a SchemaFilter that detects that attribute and removes the property from the Schema model.

@wizofaus
Copy link

Have you tried [Obsolete]?

@arisliang
Copy link

[JsonIgnore] seems to be a more natural choice for this feature.

@wizofaus
Copy link

[JsonIgnore] seems to be a more natural choice for this feature.

That prevents it from being serialized.
[Obsolete] allows serialization but prevents it from showing in the swagger output (and can trigger warnings when you reference it, which in my case is what I want, as the field is intended to be phased out but I wish to keep for backward-compatibility purposes in the meantime).

@arisliang
Copy link

In FromQuery case, JsonIgnore is not working. Is there other tag we could use? Obsolete is not suitable, as it's not phase out. Doesn't have to be system attribute, does swagger provide any custom tag for this purpose?

@Sandeep321
Copy link

@arisliang Please check and try out my answer above, it's working for me.

@frantel90
Copy link

None of the methods above work for me. I am using .NET Core 2.2.

  • [DataContract] ends up showing all members anyway
  • marking attribute as 'internal' or [JsonIgnore] doesn't deserialize the property if manually added in swaggerUI

This works for .net core 3.0 also.

@arisliang
Copy link

In the end, DataContract and DataMember worked for us.

@leadsoftlucas
Copy link

leadsoftlucas commented Jan 31, 2020

Guys, we are having the same problem on net Core 3.1.10
Swashbuckle.AspNetCore.Swagger -Version 5.0.0-rc4 is working fine!
Swashbuckle.AspNetCore.Swagger -Version 5.0.0 stopped working...

Swagger is not respecting "[DataMember]" for displaying or not properties on [DataContract] classes.
Hidden properties were shown either. Did something change? The stable release is not working as well.

@ThisNoName
Copy link

Same with JsonIgnore and/or IgnoreDataMember, works up to -rc4

@shankarab
Copy link

I'm using .net core 3.1, using the [JsonIgnore] from System.Text.Json.Serialization works. (if it used from NewtonSoft.Json, it doesn't!)

@domaindrivendev
Copy link
Owner

https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#systemtextjson-stj-vs-newtonsoft

@arisliang
Copy link

I added "services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()", but it still doesn't respect newtonsoft JsonIgnore.
I'm using core 2.1, and Swashbuckle 5.1

@antoniodlp
Copy link

Thank you @shankarab, your solution works.

@GuilhermeHenriqueBilonia

@shankarab "I'm using .net core 3.1, using the [JsonIgnore] from System.Text.Json.Serialization works. (if it used from NewtonSoft.Json, it doesn't!)"

Thanks for your answer. it work's for me.

@xts-velkumars
Copy link

JsonIgnore doesn't work for me

me as well

@williamb-egov
Copy link

I added "services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()", but it still doesn't respect newtonsoft JsonIgnore.
I'm using core 2.1, and Swashbuckle 5.1

@ugrasergun
Copy link

I'm using .net core 3.1, using the [JsonIgnore] from System.Text.Json.Serialization works. (if it used from NewtonSoft.Json, it doesn't!)

Yes this helps I was using JsonIgnore from "Newtonsoft.Json"

@MarcChapar
Copy link

[JsonIgnore] will work if the property is in the request's body, as it prevents it from being deserialized. If the property comes from the query string, it will not work.

In that case you could use [BindNever] from Microsoft.AspNetCore.Mvc.ModelBinding, this will make the model binder ignore that property and it will no longer be shown in swagger.

@AldineRuturi
Copy link

If using .netcore below v3 and Swashbuckle 5.xxx either add services.AddSwaggerGenNewtonsoftSupport() or downgrade to Swashbuckle 4.xxx. If on .netcore 3 then use Swashbuckle 5.xxx and ensure you reference [JsonIgnore] from System.Text.Json.Serialization and not NewtonSoft.Json. This is because .netcore v3+ no longer uses NewtonSoft.Json as default

@pdevito3
Copy link

FWIW, I wanted to do this for the request parameter and non of the above worked. I had to make my properties internal and that did the trick

@vickyRathee
Copy link

You my create a new [SwaggerIgnore] attribute to use that anywhere in your class. Something similar JsonIgnore, but for Swagger UI

Create a attribute
SwaggerIgnoreAttribute.cs

using System;
namespace TestApi.Attributes
{
    public class SwaggerIgnoreAttribute : Attribute
    {

    }
}

Create a filter
SwaggerSkipPropertyFilter.cs

using Microsoft.OpenApi.Models;
using TestApi.Attributes;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;

namespace TestApi.Filters
{
    public class SwaggerSkipPropertyFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (schema?.Properties == null)
            {
                return;
            }

            var skipProperties = context.Type.GetProperties().Where(t => t.GetCustomAttribute<SwaggerIgnoreAttribute>() != null);

            foreach (var skipProperty in skipProperties)
            {
                var propertyToSkip = schema.Properties.Keys.SingleOrDefault(x => string.Equals(x, skipProperty.Name, StringComparison.OrdinalIgnoreCase));

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

Add to Startup.cs
Startup.cs

 services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
                c.SchemaFilter<SwaggerSkipPropertyFilter >();
});

Use in your class

public class User
{
        [SwaggerIgnore]
        public long user_id { get; set; }
}

@IanMercer
Copy link

Latest version, [JsonIgnore] is working fine, just make sure you have the correct one, or add both to be sure :)

    [System.Text.Json.Serialization.JsonIgnore]
    [Newtonsoft.Json.JsonIgnore]

@wizofaus
Copy link

wizofaus commented Jan 5, 2021

Latest version, [JsonIgnore] is working fine, just make sure you have the correct one, or add both to be sure :)

    [System.Text.Json.Serialization.JsonIgnore]
    [Newtonsoft.Json.JsonIgnore]

Yes but as mentioned above, that prevents the property from being serialized at all.

@ksadralodabaisti
Copy link

I'm using .net core 3.1, using the [JsonIgnore] from System.Text.Json.Serialization works. (if it used from NewtonSoft.Json, it doesn't!)

This doesn't work in a scenario where you derive from a class and have a property with the "new" keyword to hide the base property.

@AlexHimself
Copy link

Latest version, [JsonIgnore] is working fine, just make sure you have the correct one, or add both to be sure :)

    [System.Text.Json.Serialization.JsonIgnore]
    [Newtonsoft.Json.JsonIgnore]

This doesn't seem to work if your controller argument is a contract class that contains a [JsonIgnore] property.

@breaker05
Copy link

Hope this can help someone, but when using FromQuery there is no serialization happening as they are simply key/values, so to ignore fields when using FromQuery, decorate your property with the [BindNever] attribute.

@NicoAleC
Copy link

NicoAleC commented May 6, 2021

Use the [DataContract] for the model and use [DataMember] for the properties which you want to show in Swagger. Any property which isn't marked as [DataMember] doesn't show up in your swagger definition. Let me know if this works or not.

This solution worked for me, thanks a lot

also, to add a greater solution put [IgnoreDataMember] to ignore some attributes or properties you want to ignore

@kodemunkey77
Copy link

Hope this can help someone, but when using FromQuery there is no serialization happening as they are simply key/values, so to ignore fields when using FromQuery, decorate your property with the [BindNever] attribute.

@breaker05 - Thanks, your solution was exactly what I needed for my project!

@Brhav
Copy link

Brhav commented Aug 10, 2021

If you want to use the [SwaggerIgnore] attribute (Credits to @vickyRathee) with NSwag:

Create a attribute
SwaggerIgnoreAttribute.cs

using System;
namespace TestApi.Attributes
{
    public class SwaggerIgnoreAttribute : Attribute
    {

    }
}

Create a schema processor
SwaggerSkipPropertySchemaProcessor.cs

using NJsonSchema.Generation;
using TestApi.Attributes;
using System;
using System.Linq;
using System.Reflection;

namespace TestApi.SchemaProcessors
{
   public class SwaggerSkipPropertySchemaProcessor : ISchemaProcessor
   {
       public void Process(SchemaProcessorContext context)
       {
           if (context.Schema?.Properties == null)
           {
               return;
           }

           var skipProperties = context.Type.GetProperties().Where(t => t.GetCustomAttribute<SwaggerIgnoreAttribute>() != null);

           foreach (var skipProperty in skipProperties)
           {
               var propertyToSkip = context.Schema.Properties.Keys.SingleOrDefault(x => string.Equals(x, skipProperty.Name, StringComparison.OrdinalIgnoreCase));

               if (propertyToSkip != null)
               {
                   context.Schema.Properties.Remove(propertyToSkip);
               }
           }
       }
   }
}

Add to Startup.cs
Startup.cs

services.AddOpenApiDocument(configure =>
{
   configure.SchemaProcessors.Add(new SwaggerSkipPropertySchemaProcessor());
});

Use in your class

public class User
{
        [SwaggerIgnore]
        public long user_id { get; set; }
}

@shelterless
Copy link

i find finall solution :

https://dejanstojanovic.net/aspnet/2019/october/ignoring-properties-from-controller-action-model-in-swagger-using-jsonignore/

it 's work for me

@selcukgural
Copy link

Hope this can help someone, but when using FromQuery there is no serialization happening as they are simply key/values, so to ignore fields when using FromQuery, decorate your property with the [BindNever] attribute.

It's working. Thank you. I've never heard of this attribute.

@nhontran
Copy link

nhontran commented Nov 4, 2022

Hope this can help someone, but when using FromQuery there is no serialization happening as they are simply key/values, so to ignore fields when using FromQuery, decorate your property with the [BindNever] attribute.

It's working for my case using FromQuery. Thank you!

@ScottHoward4
Copy link

If you want to use the [SwaggerIgnore] attribute (Credits to @vickyRathee) with NSwag:

Create a attribute SwaggerIgnoreAttribute.cs

using System;
namespace TestApi.Attributes
{
    public class SwaggerIgnoreAttribute : Attribute
    {

    }
}

Create a schema processor SwaggerSkipPropertySchemaProcessor.cs

using NJsonSchema.Generation;
using TestApi.Attributes;
using System;
using System.Linq;
using System.Reflection;

namespace TestApi.SchemaProcessors
{
   public class SwaggerSkipPropertySchemaProcessor : ISchemaProcessor
   {
       public void Process(SchemaProcessorContext context)
       {
           if (context.Schema?.Properties == null)
           {
               return;
           }

           var skipProperties = context.Type.GetProperties().Where(t => t.GetCustomAttribute<SwaggerIgnoreAttribute>() != null);

           foreach (var skipProperty in skipProperties)
           {
               var propertyToSkip = context.Schema.Properties.Keys.SingleOrDefault(x => string.Equals(x, skipProperty.Name, StringComparison.OrdinalIgnoreCase));

               if (propertyToSkip != null)
               {
                   context.Schema.Properties.Remove(propertyToSkip);
               }
           }
       }
   }
}

Add to Startup.cs Startup.cs

services.AddOpenApiDocument(configure =>
{
   configure.SchemaProcessors.Add(new SwaggerSkipPropertySchemaProcessor());
});

Use in your class

public class User
{
        [SwaggerIgnore]
        public long user_id { get; set; }
}

For some reason this works with base classes but if you have a child class that also has [SwaggerIgnore] then it wont actually be ignored.

@ScottHoward4
Copy link

ScottHoward4 commented Jan 24, 2023

using NJsonSchema.Generation;
using System;
using System.Linq;
using System.Reflection;

namespace Business.Features.Swagger
{
    public class SwaggerSkipPropertySchemaProcessor : ISchemaProcessor
    {
        public void Process(SchemaProcessorContext context)
        {
            if (context.Schema?.Properties == null)
            {
                return;
            }
            
            var skipProperties = context.ContextualType.Type.GetProperties()
                .Where(_ => _.GetCustomAttribute<SwaggerIgnoreAttribute>() != null);

            foreach (var skipProperty in skipProperties)
            {
                var propertyToSkip = context.Schema.ActualProperties.Keys.SingleOrDefault(
                    _ => string.Equals(_, skipProperty.Name, StringComparison.OrdinalIgnoreCase));

                if (propertyToSkip == null)
                    continue;
                
                if (context.Schema.Properties.ContainsKey(propertyToSkip))
                    context.Schema.Properties.Remove(propertyToSkip);
                else
                {
                    foreach (var schema in context.Schema.AllOf)
                    {
                        if(schema.Properties.ContainsKey(propertyToSkip))
                            schema.Properties.Remove(propertyToSkip);
                    }
                }
            }
        }
    }
} 

As an update to my last comment, I figured out how to fix it using this updated version of the code. Not really sure why it is this way, but if your class is a child class it may have multiple JsonSchema's in the AllOf variable, but no properties in the Properties variable. Or maybe it defaults to showing the properties of the parent class, not really sure. But regardless, I found that I can check if Properties contains the property to skip, then check if AllOf contains the property to skip and removing it from either seems to accomplish the same thing.

The other change I made is to use ActualProperties to search for the property to skip, because this always contains all the properties including the parent. ActualProperties is readonly though, so you can't remove from it.

And the final change is that I used ContextualType.Type instead of Type because it said that Type is obsolete now. It didn't seem to make any difference but w/e

If someone understands this better than me please explain because I don't really understand why it is this way. It's also possible that it's a slight bug

@jjxtra
Copy link

jjxtra commented Apr 14, 2023

Only the schema filter answer is correct. JsonIgnore or IgnoreDataMember are terrible ideas if you care about the property serializing properly. Wish the SwaggerIgnore attribute was part of the nuget package.

@KillerBoogie
Copy link

The above solutions didn't work for me, because I'm using a single class to collect all parameters. There are currently general issues collecting all parameters in a single class (dotnet/AspNetCore.Docs#29295). Options to hide are [FromServices], ISchemaFilter, IOperationFilter, and from the Annotation Extension library [SwaggerSchema(ReadOnly = true)]. None of them work in all scenarios, but some workarounds are possible. See my post: (domaindrivendev/Swashbuckle.AspNetCore#2652).
It is not understanding why there is no out of the box support for a swagger ignore attribute. [SwaggerSchema(ReadOnly = true)] needs to be fixed to work for all scenarios.

@codelovercc
Copy link

Hi,
schema.Properties is empty, it's count is 0, why ??? Swashbuckle.AspNetCore 6.5.0

@HorselessName
Copy link

So... Did anyone managed to achieve this? :(

@marcelofilhomagicmedia
Copy link

You my create a new [SwaggerIgnore] attribute to use that anywhere in your class. Something similar JsonIgnore, but for Swagger UI

Create a attribute SwaggerIgnoreAttribute.cs

using System;
namespace TestApi.Attributes
{
    public class SwaggerIgnoreAttribute : Attribute
    {

    }
}

Create a filter SwaggerSkipPropertyFilter.cs

using Microsoft.OpenApi.Models;
using TestApi.Attributes;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;

namespace TestApi.Filters
{
    public class SwaggerSkipPropertyFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (schema?.Properties == null)
            {
                return;
            }

            var skipProperties = context.Type.GetProperties().Where(t => t.GetCustomAttribute<SwaggerIgnoreAttribute>() != null);

            foreach (var skipProperty in skipProperties)
            {
                var propertyToSkip = schema.Properties.Keys.SingleOrDefault(x => string.Equals(x, skipProperty.Name, StringComparison.OrdinalIgnoreCase));

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

Add to Startup.cs Startup.cs

 services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
                c.SchemaFilter<SwaggerSkipPropertyFilter >();
});

Use in your class

public class User
{
        [SwaggerIgnore]
        public long user_id { get; set; }
}

didnt work :(

@marcelofilhomagicmedia
Copy link

ISchemaProcessor

cannot found ISchemaProcessor

@marcelofilhomagicmedia
Copy link

So... Did anyone managed to achieve this? :(

same bro

@JucimarioSilva
Copy link

I wanted to do it like this:

public class User
{
[BindNever]
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonProperty("user_id ")]
public long user_id { get; to define; }
}

@gokayokutucu
Copy link

Try this:

using System.Reflection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace TestApi.Filters
{
  public class IgnoreMeDocumentFilter : IDocumentFilter
   {
      public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
      {
          foreach (var schema in swaggerDoc.Components.Schemas)
          {
              var schemaType = context.ApiDescriptions
                  .SelectMany(desc => desc.ParameterDescriptions)
                  .Where(param => param.Type is not null && param.Type.Name == schema.Key)
                  .Select(param => param.Type)
                  .FirstOrDefault();
  
              if (schemaType == null)
                  continue;
  
              var propsToRemove = schemaType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                  .Where(prop => prop.GetCustomAttribute<IgnoreMeAttribute>() != null)
                  .Select(prop => prop.Name.ToCamelCase()) 
                  .ToList();
  
              foreach (var property in propsToRemove.Where(property => schema.Value.Properties.ContainsKey(property)))
              {
                  schema.Value.Properties.Remove(property);
              }
          }
      }
  }
}

Define an empty marker attribute:

[AttributeUsage(AttributeTargets.Property)]
public class IgnoreMeAttribute : Attribute;

Regiter in Program.cs:

services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
                c.DocumentFilter<IgnoreMeDocumentFilter>();
});

String extension:

 public static class StringExtensions
    {
        public static string ToCamelCase(this string input)
        {
            if (string.IsNullOrEmpty(input) || char.IsLower(input[0]))
            {
                return input;
            }

            var chars = input.ToCharArray();
            chars[0] = char.ToLowerInvariant(input[0]);

            return new string(chars);
        }
}

Use like this:

public record SignIn(
    string Username, string Password,
    [property:BindNever]
    [property: JsonIgnore]
    [property: IgnoreMe]
    MyHiddenType MyHiddenProp)
    : IRequest<MyResponse?>;
    
    
   [HttpPost("sign-in")]
    [Produces("application/json")]
    public async Task<IActionResult> Login(SignIn query,
        CancellationToken cancellationToken)
    {
       return Ok(await sender.Send(query, cancellationToken));
    }   

@wizofaus
Copy link

wizofaus commented Aug 24, 2024

Swashbuckle.AspNetCore.Annotations 6.6.2 has SwaggerIgnore/SwaggerIgnoreAttribute, it works fine. Not sure when it was introduced.

@Brhav
Copy link

Brhav commented Sep 9, 2024

Swashbuckle.AspNetCore.Annotations 6.6.2 has SwaggerIgnore/SwaggerIgnoreAttribute, it works fine. Not sure when it was introduced.

This doesn't work on properties

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests