NSwag 自定义 JSON 输出

zya*_*ash 4 c# asp.net-web-api swagger nswag

我有一堂课:

class Test {
  public IPAddress Ip {get; set; }
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,Nswag.AspNetCore位于http://localhost:1234/swagger 的Nswag(包)将其序列化,在预览“示例”输出中:

[    
  "Ip": {
     "AddressFamily": 0,
     "ScopeId": 0,
     "IsIPv6Multicast": true,
     "IsIPv6LinkLocal": true,
     "IsIPv6SiteLocal": true,
     "IsIPv6Teredo": true,
     "IsIPv4MappedToIPv6": true,
     "Address": 0
    }
]
Run Code Online (Sandbox Code Playgroud)

我想自定义它,以便它仅将 Ip 字段序列化为 astring而没有IPAddress.

为此,我创建了自己的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并验证它适用于 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);
Run Code Online (Sandbox Code Playgroud)

现在我想把它插入到 NSwag 中。我在 ASP.Net 的 Startup.cs 中修改了 NSwag 设置:

    // 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);
 }
Run Code Online (Sandbox Code Playgroud)

#

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;
    }
} 
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我浏览到http://localhost:1234/swagger以查看我的Test类的 Json“示例”输出时,它仍然包含IPAddress而不是Ip字段的所有属性被序列化为一个简单的string.

当我调试时,我可以看到里面的代码CustomSwaggerContractResolver被调用,转换器被分配,但它IPAddressConverter本身从未被调用。

有什么我想念的吗?

谢谢你。

Ric*_*ter 5

因为转换器的转换不能被反映(它是程序性的)你需要添加一个类型映射器

https://github.com/RSuter/NJsonSchema/wiki/Type-Mappers

并将 ipaddress 类型映射到一个简单的字符串模式

(NJsonSchema 是 NSwag 的基础)