如何创建一个自定义的 JSchemaGenerationProvider,为模型和模型的属性添加标题属性?

Nat*_*nna 4 c# json.net jsonschema

我正在使用 Newtonsoft.Json.Schema 包来生成 JSON 模式。目前,模式不包含“标题”属性,因此我按照文档中的示例创建了一个自定义提供程序,但是该提供程序仅在父节点上运行并跳过所有属性节点。

class User {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedDate { get; set; }
}

class TitleProvider : JSchemaGenerationProvider {
    public override JSchema GetSchema(JSchemaTypeGenerationContext context) {
        var schema = new JSchemaGenerator().Generate(context.ObjectType);
        schema.Title = "foo";
        return schema;
    }
}

public class Program {
    public static void Main() {
        var generator = new JSchemaGenerator();
        generator.GenerationProviders.Add(new TitleProvider());
        var schema = generator.Generate(typeof(User));

        Console.WriteLine(schema);
    }
}
// OUTPUT:
//{
//  "title": "foo",
//  "type": "object",
//  "properties": {
//    "Id": {
//      "type": "integer"
//    },
//    "Name": {
//      "type": [
//        "string",
//        "null"
//      ]
//    },
//    "CreatedDate": {
//      "type": "string"
//    }
//  },
//  "required": [
//    "Id",
//    "Name",
//    "CreatedDate"
//  ]
//}
Run Code Online (Sandbox Code Playgroud)

如何配置此提供程序以在属性节点上运行(类似于链接文档中提供的示例)?

其他注意事项:

  • 如果您从 providerGetSchema方法返回 null ,它会迭代所有属性(我在调试器中观察到),尽管它没有我想要的功能
  • 如果我添加一个 if 块以在当前 context.ObjectType 具有属性时跳过,它会遍历所有属性,但只会将标题添加到第一个属性

Nat*_*nna 5

所以我最终下载了代码并逐步执行它,发现一旦您的提供者返回一个架构,它就会绕过当前节点下所有节点的所有默认处理。因此,您几乎必须自己进行所有解析,或者以某种方式解决默认行为。我最终创建了一个提供程序,它允许您在每个节点上执行您的逻辑,但仍然为您提供默认生成的架构来使用:

abstract class RecursiveProvider : JSchemaGenerationProvider {
    public string SkipType { get; set; }
    public override JSchema GetSchema(JSchemaTypeGenerationContext context) {
        var type = context.ObjectType;
        JSchema schema = null;

        var generator = new JSchemaGenerator();

        Console.WriteLine(type.Name);

        var isObject = type.Namespace != "System";

        if (isObject) {
            if (SkipType == type.Name)
                return null;

            this.SkipType = type.Name;
            generator.GenerationProviders.Add(this);
        }

        schema = generator.Generate(type);
        return ModifySchema(schema, context);
    }

    public abstract JSchema ModifySchema(JSchema schema, JSchemaTypeGenerationContext context);

}

class PropertyProvider : RecursiveProvider {
    public override JSchema ModifySchema(JSchema schema, JSchemaTypeGenerationContext context) {
        schema.Title = "My Title";
        return schema;
    }
}
Run Code Online (Sandbox Code Playgroud)