You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:23:34