Json.Net.Schema:如何生成仅需要 [Required] 属性的架构?
Json.Net.Schema: How to generate a schema where only the [Required] properties are required?
我正在编写一个工具来处理 resume.json 文件 (project),并且正在创建一个 Json 架构来验证用户输入。我正在尝试使用 Json.Net.Schema 自动执行此操作,但输出始终需要所有属性,无论属性是否具有 [Required]
或 [JsonRequired]
属性。
模式生成代码
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName
};
var schema = generator.Generate(typeof(Resume));
var sb = new StringBuilder();
schema.WriteTo(new JsonTextWriter(
new IndentedTextWriter(
new StringWriter(sb),
" ")
)
{
Formatting = Formatting.Indented,
IndentChar = ' ', Indentation = 2,
QuoteName = true
}, new JSchemaWriterSettings
{
Version = SchemaVersion.Draft7
});
File.WriteAllText("E:\resume.schema", sb.ToString());
恢复 Class(和 children)
public class Resume
{
[Required]
public Basics Basics { get; set; }
public Work[] Work { get; set; }
public Volunteer[] Volunteer { get; set; }
public Education[] Education { get; set; }
public Award[] Awards { get; set; }
public Publication[] Publications { get; set; }
public Skill[] Skills { get; set; }
public Language[] Languages { get; set; }
public Interest[] Interests { get; set; }
public Reference[] References { get; set; }
}
public class Award
{
[Required]
public string Title { get; set; }
public string Date { get; set; }
public string Awarder { get; set; }
public string Summary { get; set; }
}
public class Basics
{
[Required]
public string Name { get; set; }
public string Label { get; set; }
public Uri Picture { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
public Location Location { get; set; }
public Profile[] Profiles { get; set; }
}
public class Education
{
[Required]
public string Institution { get; set; }
public string Area { get; set; }
public string StudyType { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Gpa { get; set; }
public string[] Courses { get; set; }
}
public class Interest
{
[Required]
public string Name { get; set; }
public string[] Keywords { get; set; }
}
public class Language
{
[Required]
public string language { get; set; }
[Required]
public string Fluency { get; set; }
}
public class Location
{
public string Address { get; set; }
[Required]
public string PostalCode { get; set; }
[Required]
public string City { get; set; }
[Required]
public string CountryCode { get; set; }
public string Region { get; set; }
}
public class Profile
{
[Required]
public string Network { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Url { get; set; }
}
public class Publication
{
[Required]
public string Name { get; set; }
public string Publisher { get; set; }
public string ReleaseDate { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
}
public class Reference
{
[Required]
public string Name { get; set; }
public string reference { get; set; }
}
public class Skill
{
[Required]
public string Name { get; set; }
[Required]
public string Level { get; set; }
public string[] Keywords { get; set; }
}
public class Volunteer
{
[Required]
public string Organization { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
public class Work
{
[Required]
public string Company { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
[Required]
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
当前输出
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "Resume",
"definitions": {
"Award": {
"$id": "Award",
"type": [
"object",
"null"
],
"properties": {
"title": {
"type": "string"
},
"date": {
"type": [
"string",
"null"
]
},
"awarder": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"title",
"date",
"awarder",
"summary"
]
},
"Basics": {
"$id": "Basics",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"label": {
"type": [
"string",
"null"
]
},
"picture": {
"type": [
"string",
"null"
],
"format": "uri"
},
"email": {
"type": [
"string",
"null"
]
},
"phone": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"location": {
"$id": "Location",
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": [
"string",
"null"
]
},
"postalCode": {
"type": "string"
},
"city": {
"type": "string"
},
"countryCode": {
"type": "string"
},
"region": {
"type": [
"string",
"null"
]
}
},
"required": [
"address",
"postalCode",
"city",
"countryCode",
"region"
]
},
"profiles": {
"$id": "Profile[]",
"type": [
"array",
"null"
],
"items": {
"$id": "Profile",
"type": [
"object",
"null"
],
"properties": {
"network": {
"type": "string"
},
"username": {
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"network",
"username",
"url"
]
}
}
},
"required": [
"name",
"label",
"picture",
"email",
"phone",
"website",
"summary",
"location",
"profiles"
]
},
"Education": {
"$id": "Education",
"type": [
"object",
"null"
],
"properties": {
"institution": {
"type": "string"
},
"area": {
"type": [
"string",
"null"
]
},
"studyType": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"gpa": {
"type": [
"string",
"null"
]
},
"courses": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"institution",
"area",
"studyType",
"startDate",
"endDate",
"gpa",
"courses"
]
},
"Interest": {
"$id": "Interest",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"keywords"
]
},
"Language": {
"$id": "Language",
"type": [
"object",
"null"
],
"properties": {
"language": {
"type": "string"
},
"fluency": {
"type": "string"
}
},
"required": [
"language",
"fluency"
]
},
"Location": {
"$ref": "Location"
},
"Profile": {
"$ref": "Profile"
},
"Publication": {
"$id": "Publication",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"publisher": {
"type": [
"string",
"null"
]
},
"releaseDate": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"publisher",
"releaseDate",
"website",
"summary"
]
},
"Reference": {
"$id": "Reference",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"reference": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"reference"
]
},
"Skill": {
"$id": "Skill",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"level": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"level",
"keywords"
]
},
"Volunteer": {
"$id": "Volunteer",
"type": [
"object",
"null"
],
"properties": {
"organization": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"organization",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
},
"Work": {
"$id": "Work",
"type": [
"object",
"null"
],
"properties": {
"company": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": "string"
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"company",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
}
},
"type": "object",
"properties": {
"basics": {
"$ref": "Basics"
},
"work": {
"$id": "Work[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Work"
}
},
"volunteer": {
"$id": "Volunteer[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Volunteer"
}
},
"education": {
"$id": "Education[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Education"
}
},
"awards": {
"$id": "Award[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Award"
}
},
"publications": {
"$id": "Publication[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Publication"
}
},
"skills": {
"$id": "Skill[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Skill"
}
},
"languages": {
"$id": "Language[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Language"
}
},
"interests": {
"$id": "Interest[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Interest"
}
},
"references": {
"$id": "Reference[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Reference"
}
}
},
"required": [
"basics",
"work",
"volunteer",
"education",
"awards",
"publications",
"skills",
"languages",
"interests",
"references"
]
}
如何让架构生成器遵守 Required
属性?
JSchemaGenerator
has a property DefaultRequired
:
Gets or sets the default required state of schemas.
出于某种原因,此 属性 的默认值为 Required.AllowNull
,如 source:
所示
public JSchemaGenerator()
{
_schemaReferenceHandling = SchemaReferenceHandling.Objects;
_defaultRequired = Required.AllowNull;
}
如果将其更改为 Required.Default
, only those properties explicitly marked as required, e.g. with [Required]
or [JsonProperty(Required = Required.Always)]
,将在架构中按要求列出:
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName,
DefaultRequired = Required.Default,
};
DefaultRequired
的默认值不是 documented, but probably should be. You might open an issue,Newtonsoft 要求对文档进行说明。
演示 fiddle here.
我正在编写一个工具来处理 resume.json 文件 (project),并且正在创建一个 Json 架构来验证用户输入。我正在尝试使用 Json.Net.Schema 自动执行此操作,但输出始终需要所有属性,无论属性是否具有 [Required]
或 [JsonRequired]
属性。
模式生成代码
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName
};
var schema = generator.Generate(typeof(Resume));
var sb = new StringBuilder();
schema.WriteTo(new JsonTextWriter(
new IndentedTextWriter(
new StringWriter(sb),
" ")
)
{
Formatting = Formatting.Indented,
IndentChar = ' ', Indentation = 2,
QuoteName = true
}, new JSchemaWriterSettings
{
Version = SchemaVersion.Draft7
});
File.WriteAllText("E:\resume.schema", sb.ToString());
恢复 Class(和 children)
public class Resume
{
[Required]
public Basics Basics { get; set; }
public Work[] Work { get; set; }
public Volunteer[] Volunteer { get; set; }
public Education[] Education { get; set; }
public Award[] Awards { get; set; }
public Publication[] Publications { get; set; }
public Skill[] Skills { get; set; }
public Language[] Languages { get; set; }
public Interest[] Interests { get; set; }
public Reference[] References { get; set; }
}
public class Award
{
[Required]
public string Title { get; set; }
public string Date { get; set; }
public string Awarder { get; set; }
public string Summary { get; set; }
}
public class Basics
{
[Required]
public string Name { get; set; }
public string Label { get; set; }
public Uri Picture { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
public Location Location { get; set; }
public Profile[] Profiles { get; set; }
}
public class Education
{
[Required]
public string Institution { get; set; }
public string Area { get; set; }
public string StudyType { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Gpa { get; set; }
public string[] Courses { get; set; }
}
public class Interest
{
[Required]
public string Name { get; set; }
public string[] Keywords { get; set; }
}
public class Language
{
[Required]
public string language { get; set; }
[Required]
public string Fluency { get; set; }
}
public class Location
{
public string Address { get; set; }
[Required]
public string PostalCode { get; set; }
[Required]
public string City { get; set; }
[Required]
public string CountryCode { get; set; }
public string Region { get; set; }
}
public class Profile
{
[Required]
public string Network { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Url { get; set; }
}
public class Publication
{
[Required]
public string Name { get; set; }
public string Publisher { get; set; }
public string ReleaseDate { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
}
public class Reference
{
[Required]
public string Name { get; set; }
public string reference { get; set; }
}
public class Skill
{
[Required]
public string Name { get; set; }
[Required]
public string Level { get; set; }
public string[] Keywords { get; set; }
}
public class Volunteer
{
[Required]
public string Organization { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
public class Work
{
[Required]
public string Company { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
[Required]
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
当前输出
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "Resume",
"definitions": {
"Award": {
"$id": "Award",
"type": [
"object",
"null"
],
"properties": {
"title": {
"type": "string"
},
"date": {
"type": [
"string",
"null"
]
},
"awarder": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"title",
"date",
"awarder",
"summary"
]
},
"Basics": {
"$id": "Basics",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"label": {
"type": [
"string",
"null"
]
},
"picture": {
"type": [
"string",
"null"
],
"format": "uri"
},
"email": {
"type": [
"string",
"null"
]
},
"phone": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"location": {
"$id": "Location",
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": [
"string",
"null"
]
},
"postalCode": {
"type": "string"
},
"city": {
"type": "string"
},
"countryCode": {
"type": "string"
},
"region": {
"type": [
"string",
"null"
]
}
},
"required": [
"address",
"postalCode",
"city",
"countryCode",
"region"
]
},
"profiles": {
"$id": "Profile[]",
"type": [
"array",
"null"
],
"items": {
"$id": "Profile",
"type": [
"object",
"null"
],
"properties": {
"network": {
"type": "string"
},
"username": {
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"network",
"username",
"url"
]
}
}
},
"required": [
"name",
"label",
"picture",
"email",
"phone",
"website",
"summary",
"location",
"profiles"
]
},
"Education": {
"$id": "Education",
"type": [
"object",
"null"
],
"properties": {
"institution": {
"type": "string"
},
"area": {
"type": [
"string",
"null"
]
},
"studyType": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"gpa": {
"type": [
"string",
"null"
]
},
"courses": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"institution",
"area",
"studyType",
"startDate",
"endDate",
"gpa",
"courses"
]
},
"Interest": {
"$id": "Interest",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"keywords"
]
},
"Language": {
"$id": "Language",
"type": [
"object",
"null"
],
"properties": {
"language": {
"type": "string"
},
"fluency": {
"type": "string"
}
},
"required": [
"language",
"fluency"
]
},
"Location": {
"$ref": "Location"
},
"Profile": {
"$ref": "Profile"
},
"Publication": {
"$id": "Publication",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"publisher": {
"type": [
"string",
"null"
]
},
"releaseDate": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"publisher",
"releaseDate",
"website",
"summary"
]
},
"Reference": {
"$id": "Reference",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"reference": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"reference"
]
},
"Skill": {
"$id": "Skill",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"level": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"level",
"keywords"
]
},
"Volunteer": {
"$id": "Volunteer",
"type": [
"object",
"null"
],
"properties": {
"organization": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"organization",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
},
"Work": {
"$id": "Work",
"type": [
"object",
"null"
],
"properties": {
"company": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": "string"
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"company",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
}
},
"type": "object",
"properties": {
"basics": {
"$ref": "Basics"
},
"work": {
"$id": "Work[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Work"
}
},
"volunteer": {
"$id": "Volunteer[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Volunteer"
}
},
"education": {
"$id": "Education[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Education"
}
},
"awards": {
"$id": "Award[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Award"
}
},
"publications": {
"$id": "Publication[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Publication"
}
},
"skills": {
"$id": "Skill[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Skill"
}
},
"languages": {
"$id": "Language[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Language"
}
},
"interests": {
"$id": "Interest[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Interest"
}
},
"references": {
"$id": "Reference[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Reference"
}
}
},
"required": [
"basics",
"work",
"volunteer",
"education",
"awards",
"publications",
"skills",
"languages",
"interests",
"references"
]
}
如何让架构生成器遵守 Required
属性?
JSchemaGenerator
has a property DefaultRequired
:
Gets or sets the default required state of schemas.
出于某种原因,此 属性 的默认值为 Required.AllowNull
,如 source:
public JSchemaGenerator()
{
_schemaReferenceHandling = SchemaReferenceHandling.Objects;
_defaultRequired = Required.AllowNull;
}
如果将其更改为 Required.Default
, only those properties explicitly marked as required, e.g. with [Required]
or [JsonProperty(Required = Required.Always)]
,将在架构中按要求列出:
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName,
DefaultRequired = Required.Default,
};
DefaultRequired
的默认值不是 documented, but probably should be. You might open an issue,Newtonsoft 要求对文档进行说明。
演示 fiddle here.