Reputation: 732
I have a class:
class Test {
public IPAddress Ip {get; set; }
}
By default, Nswag (Nswag.AspNetCore
package) at http://localhost:1234/swagger serializes it as so, in the preview "Example" output:
[
"Ip": {
"AddressFamily": 0,
"ScopeId": 0,
"IsIPv6Multicast": true,
"IsIPv6LinkLocal": true,
"IsIPv6SiteLocal": true,
"IsIPv6Teredo": true,
"IsIPv4MappedToIPv6": true,
"Address": 0
}
]
I want to custimize it, so that it serializes just the Ip field as a string
without all the other type properties of IPAddress
.
To do that, I created my own JsonConverter
:
public class IPAddressConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPAddress));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
}
And verified that it works with JSON.Net.
var settings = new JsonSerializerSettings() { Converters = { new IPAddressConverter() } };
JsonConvert.SerializeObject(IPAddress.Parse("123.123.123.123"), settings);
JsonConvert.DeserializeObject<IPAddress>("123.123.123.123", settings);
Now I wanted to plug this into NSwag. I modified the NSwag settings like so inside ASP.Net's Startup.cs:
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
var swaggerSettings = new SwaggerUi3Settings()
{
ContractResolver = new CustomSwaggerContractResolver(),
DefaultPropertyNameHandling = NJsonSchema.PropertyNameHandling.Default /* If this is not set to default it raises an exception when a ContractResolver is set and then swagger page does not load at all */
};
app.UseSwaggerUi3(typeof(Startup).Assembly, swaggerSettings);
}
#
public class CustomSwaggerContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
JsonContract contract = base.CreateContract(objectType);
if (objectType == typeof(IPAddress))
{
contract.Converter = new IPAddressConverter();
}
return contract;
}
}
Unfortunately when I browse to http://localhost:1234/swagger to see the Json "Example" output of my Test
class, it is still including all the properties of IPAddress
instead of Ip
field being serialized as a simple string
.
When I debug I can see that code inside CustomSwaggerContractResolver
is called, and the converter is assigned, but the IPAddressConverter
itself is never being called.
Is there anything that I am missing?
Thank you.
Upvotes: 4
Views: 10022
Reputation: 11858
Because the transformation of a converter cannot be reflected (it is procedural) you need to add a type mapper
https://github.com/RSuter/NJsonSchema/wiki/Type-Mappers
and map the ipaddress type to a simple string schema
(NJsonSchema is the base of NSwag)
Upvotes: 5