C#中如何无需自定义类重写公共库SwaggerDocument的Json.NET注解?
Got it, let's work through this. You're using a public SwaggerDocument class with hardcoded Newtonsoft.Json serialization annotations (like the JsonProperty attribute controlling DefaultValueHandling, Order, and PropertyName), and you want to adjust those settings without having to build a custom wrapper or derived class—totally get it, duplicating code just to tweak serialization rules is a hassle.
Here's the cleanest approach using Newtonsoft's ContractResolver feature, which lets you dynamically override serialization contracts at runtime:
Step 1: Build a Custom Contract Resolver
The DefaultContractResolver is Newtonsoft's core tool for defining how types are serialized. We'll subclass it to override the rules specifically for the SwaggerDocument properties you care about:
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System.Reflection; public class CustomSwaggerContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { // Start with the original contract defined by the library's annotations JsonProperty property = base.CreateProperty(member, memberSerialization); // Target the specific property you want to modify if (member.DeclaringType == typeof(SwaggerDocument) && member.Name == nameof(SwaggerDocument.BasePath)) { // Override settings to your desired values property.DefaultValueHandling = DefaultValueHandling.Include; // Replace with your preferred rule property.Order = 3; // Adjust serialization order property.PropertyName = "custom_base_path"; // Rename the JSON property if needed // You can also add tweaks like NullValueHandling here } // Add more conditions here if you need to modify other SwaggerDocument properties // Example: if (member.Name == nameof(SwaggerDocument.Title)) { ... } return property; } }
Step 2: Use the Resolver During Serialization/Deserialization
When you need to process a SwaggerDocument instance, pass your custom resolver into the JsonSerializerSettings:
// Initialize your SwaggerDocument instance var swaggerDoc = new SwaggerDocument { BasePath = "/api/v1" }; // Configure serialization with your modified rules var jsonSettings = new JsonSerializerSettings { ContractResolver = new CustomSwaggerContractResolver(), Formatting = Formatting.Indented // Optional: for pretty-printed JSON }; // Serialize using the adjusted rules string serializedJson = JsonConvert.SerializeObject(swaggerDoc, jsonSettings); // Or deserialize with the same rules if needed SwaggerDocument deserializedDoc = JsonConvert.DeserializeObject<SwaggerDocument>(jsonString, jsonSettings);
Step 3: Integrate with ASP.NET Core (If Using Swashbuckle)
If you're working in an ASP.NET Core project with Swashbuckle (Swagger), you can set up the resolver globally so Swagger uses your custom serialization rules:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); // Configure Newtonsoft.Json settings for controllers and Swagger services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new CustomSwaggerContractResolver(); });
Why This Works
- No custom class required: You're modifying behavior dynamically instead of creating a wrapper or derived class.
- Non-intrusive: The original
SwaggerDocumentclass stays untouched, so other parts of your code that use it (without the resolver) will still behave as expected. - Flexible: You can tweak multiple properties, add conditional logic, or apply global rules for the entire
SwaggerDocumenttype.
内容的提问来源于stack exchange,提问作者user171943

