NET8 Web API 项目。
我的控制器操作没有键入的输入参数。传入的 JSON 是从请求正文流中读取的,并使用 NJsonSchema 根据架构进行验证,然后发送到另一个服务或保存到数据库。未对其进行任何操作。
该项目启用了 swagger,在这种情况下,它不会显示 swagger-ui 中输入参数的方案。但我需要输入参数方案(通过它进行验证)在 UI 以及最终的 OpenAPI 规范 (swagger.json) 文件中可见。 对于这种情况有没有现成的解决方案或金块包?
我关注 Microsoft.OpenApi.Readers 包,但那里的事情有点复杂。
简化代码示例:
[HttpPost("upload")]
[ProducesResponseType<SimpleModel>(200)]
public async Task<IActionResult> Upload()
{
using var sr = new StreamReader(Request.Body);
var requestBody = await sr.ReadToEndAsync();
// Used for checking is JSON valid
var model = JObject.Parse(requestBody);
var validationErrors = _jsonSchema.Validate(model);
if (validationErrors.Count > 0)
return BadRequest(validationErrors);
/*
* do some useful non typed stuff with input model
*/
return Ok();
}
您可以使用Swagger操作过滤器来添加模式,下面是示例代码:
主控制器.cs:
using Microsoft.AspNetCore.Mvc;
using NJsonSchema;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Threading.Tasks;
namespace JsonSchemaValidationApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class MainController : ControllerBase
{
private readonly JsonSchema _jsonSchema;
public MainController()
{
// Load JSON schema from file
_jsonSchema = JsonSchema.FromFileAsync("SimpleModelSchema.json").Result;
}
[HttpPost("upload")]
[ProducesResponseType(typeof(SimpleModel), 200)]
public async Task<IActionResult> Upload()
{
using var sr = new StreamReader(Request.Body);
var requestBody = await sr.ReadToEndAsync();
// Parse the JSON and validate it against the schema
var model = JObject.Parse(requestBody);
var validationErrors = _jsonSchema.Validate(model);
if (validationErrors.Count > 0)
return BadRequest(validationErrors);
return Ok(new { Message = "JSON is valid", Data = model });
}
}
}
添加JsonSchemaOperationFilter.cs:
using Microsoft.OpenApi.Models;
using NJsonSchema;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
namespace JsonSchemaValidationApi
{
public class AddJsonSchemaOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.ApiDescription.HttpMethod.Equals("POST", System.StringComparison.OrdinalIgnoreCase))
{
// Load the JSON schema file and convert it to OpenApiSchema
var jsonSchema = LoadJsonSchema("SimpleModelSchema.json");
operation.RequestBody = new OpenApiRequestBody
{
Content = new Dictionary<string, OpenApiMediaType>
{
["application/json"] = new OpenApiMediaType
{
Schema = jsonSchema
}
}
};
}
}
private OpenApiSchema LoadJsonSchema(string filePath)
{
var json = File.ReadAllText(filePath);
var schema = JsonSchema.FromJsonAsync(json).Result;
var openApiSchema = new OpenApiSchema
{
Type = ConvertJsonObjectTypeToOpenApiType(schema.Type),
Properties = schema.Properties.ToDictionary(
prop => prop.Key,
prop => new OpenApiSchema
{
Type = ConvertJsonObjectTypeToOpenApiType(prop.Value.Type),
Format = prop.Value.Format
})
};
return openApiSchema;
}
private string ConvertJsonObjectTypeToOpenApiType(JsonObjectType jsonObjectType)
{
return jsonObjectType switch
{
JsonObjectType.String => "string",
JsonObjectType.Number => "number",
JsonObjectType.Integer => "integer",
JsonObjectType.Boolean => "boolean",
JsonObjectType.Array => "array",
JsonObjectType.Object => "object",
_ => "string"
};
}
}
}
程序.cs:
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.OperationFilter<AddJsonSchemaOperationFilter>();
});