关键字"options": { "hidden": true } 甚至"hidden": true 似乎不在当前JSON Schema specification 的validation keywords 中——或者据我所知的任何早期版本。唯一看起来相关的关键字是readOnly 和writeOnly。来自docs:
草案 7 中的新功能 布尔关键字 readOnly 和 writeOnly 通常用于 API 上下文。 readOnly 表示不应修改值。它可用于指示更改值的PUT 请求将导致400 Bad Request 响应。 writeOnly 表示可以设置一个值,但会保持隐藏。 In 可用于指示您可以使用 PUT 请求设置值,但在使用 GET 请求检索该记录时不会包含该值。
{
"title": "Match anything",
"description": "This is a schema that matches anything.",
"default": "Default value",
"examples": [
"Anything",
4035
],
"readOnly": true,
"writeOnly": false
}
因此,"options": { "hidden": true } 似乎是 JSON Schema 标准的某种自定义或第 3 方扩展。 Json.NET 架构通过 JSchema.ExtensionData 属性支持此类自定义验证关键字。要在自动模式生成期间在此扩展数据中设置隐藏选项,请定义以下 JSchemaGenerationProvider:
[System.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class HiddenAttribute : System.Attribute
{
}
public class HiddenOptionProvider : CustomizedProviderBase
{
public override JSchema GetSchema(JSchemaTypeGenerationContext context)
{
var schema = base.GetSchema(context);
// Get the JsonObjectContract for this type.
var contract = (JsonObjectContract)context.Generator.ContractResolver.ResolveContract(context.ObjectType);
foreach (var propertySchema in schema.Properties)
{
// Find the corresponding JsonProperty from the contract resolver.
var jProperty = contract.Properties[propertySchema.Key];
// Check to see if the member has HiddenAttribute set.
if (jProperty.AttributeProvider.GetAttributes(typeof(HiddenAttribute), true).Any())
// If so add "options": { "hidden": true }
propertySchema.Value.ExtensionData["options"] = new JObject(new JProperty("hidden", true));
}
return schema;
}
public override bool CanGenerateSchema(JSchemaTypeGenerationContext context) =>
base.CanGenerateSchema(context) && context.Generator.ContractResolver.ResolveContract(context.ObjectType) is JsonObjectContract;
}
public abstract class CustomizedProviderBase : JSchemaGenerationProvider
{
// Base class that allows generation of a default schema which may then be subsequently customized.
// Note this class contains state information and so is not thread safe.
readonly Stack<Type> currentTypes = new ();
public override JSchema GetSchema(JSchemaTypeGenerationContext context)
{
if (CanGenerateSchema(context))
{
var currentType = context.ObjectType;
try
{
currentTypes.Push(currentType);
return context.Generator.Generate(currentType);
}
finally
{
currentTypes.Pop();
}
}
else
throw new NotImplementedException();
}
public override bool CanGenerateSchema(JSchemaTypeGenerationContext context) =>
!currentTypes.TryPeek(out var t) || t != context.ObjectType;
}
然后定义您的Person 类型如下:
[DisplayName("Person")]
public class Person
{
[JsonProperty("name", Required = Required.DisallowNull)]
[DefaultValue("Jeremy Dorn"), MinLength(4), System.ComponentModel.DescriptionAttribute("First and Last name")]
[Hidden] // Your custom attribute
public string Name { get; set; } = "Jeremy Dorn";
}
并生成如下模式:
var generator = new JSchemaGenerator();
generator.GenerationProviders.Add(new HiddenOptionProvider());
var schema = generator.Generate(typeof(Person));
您将根据需要获得以下架构:
{
"title": "Person",
"type": "object",
"properties": {
"name": {
"description": "First and Last name",
"options": {
"hidden": true
},
"type": "string",
"default": "Jeremy Dorn",
"minLength": 4
}
}
}
演示小提琴here.