在 NET8 Web API 项目中的 swagger 中使用来自外部源的 JSON 模式

问题描述 投票:0回答:1

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 ui

c# asp.net-core-webapi openapi jsonschema swashbuckle
1个回答
0
投票

您可以使用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>();
});

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.