含IOpenApiAny属性的OpenApiDocument反序列化失败求助
解决OpenApiDocument反序列化IOpenApiAny类型的异常问题
这个问题的核心在于Newtonsoft.Json无法自动将原始JSON值(比如字符串、数字)反序列化为IOpenApiAny接口类型——因为接口不能直接实例化,Json.NET不知道该用哪个具体的实现类(比如OpenApiString、OpenApiInteger等)来匹配JSON值。
解决方案:自定义JsonConverter处理IOpenApiAny
我们可以写一个自定义的Json转换器,根据JSON值的类型来创建对应的IOpenApiAny实现类,让Json.NET知道如何处理这个接口类型。
1. 实现自定义转换器
using Microsoft.OpenApi.Any; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; public class OpenApiAnyConverter : JsonConverter<IOpenApiAny> { public override bool CanConvert(Type objectType) { return typeof(IOpenApiAny).IsAssignableFrom(objectType); } public override IOpenApiAny ReadJson(JsonReader reader, Type objectType, IOpenApiAny existingValue, bool hasExistingValue, JsonSerializer serializer) { var token = JToken.Load(reader); switch (token.Type) { case JTokenType.String: return new OpenApiString(token.Value<string>()); case JTokenType.Integer: return new OpenApiInteger(token.Value<int>()); case JTokenType.Boolean: return new OpenApiBoolean(token.Value<bool>()); case JTokenType.Float: return new OpenApiDouble(token.Value<double>()); case JTokenType.Object: var openApiObject = new OpenApiObject(); serializer.Populate(token.CreateReader(), openApiObject); return openApiObject; case JTokenType.Array: var openApiArray = new OpenApiArray(); serializer.Populate(token.CreateReader(), openApiArray); return openApiArray; case JTokenType.Null: return null; default: throw new JsonSerializationException($"Unsupported token type {token.Type} for IOpenApiAny"); } } public override void WriteJson(JsonWriter writer, IOpenApiAny value, JsonSerializer serializer) { // 序列化不需要自定义,使用默认逻辑即可 serializer.Serialize(writer, value); } }
2. 在反序列化时使用这个转换器
修改你的反序列化代码,把自定义转换器添加到JsonSerializerSettings中:
var settings = new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore, Converters = new List<JsonConverter> { new OpenApiAnyConverter() } }; // 反序列化不再抛出异常 var swagger = JsonConvert.DeserializeObject<OpenApiDocument>(serializedOpenApiDocument, settings);
3. 完整测试示例
using Microsoft.OpenApi; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Any; using Newtonsoft.Json; using System.Collections.Generic; var document = new OpenApiDocument(); var schema = new OpenApiSchema(); schema.Default = new OpenApiString("HelloDarknessMyOldFriend"); document.Components = new OpenApiComponents(); document.Components.Schemas.Add("someSchema", schema); // 序列化 string serializedOpenApiDocument = document.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json); // 反序列化(使用自定义转换器) var settings = new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore, Converters = new List<JsonConverter> { new OpenApiAnyConverter() } }; var swagger = JsonConvert.DeserializeObject<OpenApiDocument>(serializedOpenApiDocument, settings); // 验证结果 Console.WriteLine((swagger.Components.Schemas["someSchema"].Default as OpenApiString).Value); // 输出:HelloDarknessMyOldFriend
为什么这个方法有效?
自定义转换器会根据JSON值的实际类型(字符串、数字、对象等),创建对应的IOpenApiAny实现类(比如OpenApiString对应JSON字符串),这样Json.NET就有了明确的实例化规则,不会再抛出类型转换异常。
内容的提问来源于stack exchange,提问作者Roy
相关产品推荐
相关产品推荐

