NSwag | NJsonSchema | Apimundo | Namotion.Reflection
NJsonSchema is a .NET library to read, generate and validate JSON Schema draft v4+ schemas. The library can read a schema from a file or string and validate JSON data against it. A schema can also be generated from an existing .NET class. With the code generation APIs you can generate C# and TypeScript classes or interfaces from a schema.
The library uses Json.NET to read and write JSON data and Namotion.Reflection for additional .NET reflection APIs.
NuGet packages:
- NJsonSchema : JSON Schema parsing, validation and generation classes
- NJsonSchema.Annotations : JSON Schema annotations controlling serialization
- NJsonSchema.Yaml : Read and write JSON Schemas from YAML
- NJsonSchema.CodeGeneration : Base classes to generate code from a JSON Schema
- NJsonSchema.CodeGeneration.CSharp : Generates CSharp classes
- NJsonSchema.CodeGeneration.TypeScript : Generates TypeScript interfaces or classes
Preview NuGet Feed: https://www.myget.org/F/njsonschema/api/v3/index.json
Features:
- Read existing JSON Schemas and validate JSON data (
JsonSchema.FromJsonAsync()) - Generate JSON Schema from .NET type via reflection (with support for many attributes/annotations) (
JsonSchema.FromType<MyType>()) - Generate JSON Schema from sample JSON data (
JsonSchema.FromSampleJson()) - Support for schema references ($ref) (relative, URL and file)
- Generate C# and TypeScript code from JSON Schema
- Supports .NET Standard 2.0, also see XML Documentation)
- Supports JSON Schema, Swagger and OpenAPI DTO schemas
NJsonSchema is heavily used in NSwag, a Swagger API toolchain for .NET which generates client code for Web API services. NSwag also provides command line tools to use the NJsonSchema's JSON Schema generator (command types2swagger).
The project is developed and maintained by Rico Suter and other contributors.
Some code generators can directly be used via the Apimundo service.
The JsonSchema class can be used as follows:
varschema=JsonSchema.FromType<Person>();varschemaData=schema.ToJson();varerrors=schema.Validate("{...}");foreach(varerrorinerrors)Console.WriteLine(error.Path+": "+error.Kind);schema=awaitJsonSchema.FromJsonAsync(schemaData);The Person class:
publicclassPerson{[Required]publicstringFirstName{get;set;}publicstringMiddleName{get;set;}[Required]publicstringLastName{get;set;}publicGenderGender{get;set;}[Range(2,5)]publicintNumberWithRange{get;set;}publicDateTimeBirthday{get;set;}publicCompanyCompany{get;set;}publicCollection<Car>Cars{get;set;}}publicenumGender{Male,Female}publicclassCar{publicstringName{get;set;}publicCompanyManufacturer{get;set;}}publicclassCompany{publicstringName{get;set;}}The generated JSON schema data stored in the schemaData variable:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Person",
"type": "object",
"additionalProperties": false,
"required": [
"FirstName",
"LastName"
],
"properties": {
"FirstName": {
"type": "string",
"minLength": 1
},
"MiddleName": {
"type": [
"null",
"string"
]
},
"LastName": {
"type": "string",
"minLength": 1
},
"Gender": {
"$ref": "#/definitions/Gender"
},
"NumberWithRange": {
"type": "integer",
"format": "int32",
"maximum": 5.0,
"minimum": 2.0
},
"Birthday": {
"type": "string",
"format": "date-time"
},
"Company": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/definitions/Company"
}
]
},
"Cars": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/Car"
}
}
},
"definitions": {
"Gender": {
"type": "integer",
"description": "",
"x-enumNames": [
"Male",
"Female"
],
"enum": [
0,
1
]
},
"Company": {
"type": "object",
"additionalProperties": false,
"properties": {
"Name": {
"type": [
"null",
"string"
]
}
}
},
"Car": {
"type": "object",
"additionalProperties": false,
"properties": {
"Name": {
"type": [
"null",
"string"
]
},
"Manufacturer": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/definitions/Company"
}
]
}
}
}
}
}The NJsonSchema.CodeGeneration can be used to generate C# or TypeScript code from a JSON schema:
vargenerator=newCSharpGenerator(schema);varfile=generator.GenerateFile();The file variable now contains the C# code for all the classes defined in the JSON schema.
The previously generated JSON Schema would generate the following TypeScript interfaces.
Settings:
new TypeScriptGeneratorSettings { TypeStyle = TypeScriptTypeStyle.Interface, TypeScriptVersion = 4.3m }
Output:
exportenumGender{Male=0,Female=1,}exportinterfaceCompany{Name: string|undefined;}exportinterfaceCar{Name: string|undefined;Manufacturer: Company|undefined;}exportinterfacePerson{FirstName: string;MiddleName: string|undefined;LastName: string;Gender: Gender;NumberWithRange: number;Birthday: Date;Company: Company|undefined;Cars: Car[]|undefined;}... and the following TypeScript classes.
Settings:
new TypeScriptGeneratorSettings { TypeStyle = TypeScriptTypeStyle.Class, TypeScriptVersion = 4.3m }
Output:
exportenumGender{Male=0,Female=1,}exportclassCompanyimplementsICompany{name: string|undefined;constructor(data?: ICompany){if(data){for(varpropertyindata){if(data.hasOwnProperty(property))(<any>this)[property]=(<any>data)[property];}}}init(data?: any){if(data){this.name=data["Name"];}}staticfromJS(data: any): Company{letresult=newCompany();result.init(data);returnresult;}toJSON(data?: any){data=typeofdata==='object' ? data : {};data["Name"]=this.name;returndata;}}exportinterfaceICompany{name: string|undefined;}exportclassCarimplementsICar{name: string|undefined;manufacturer: Company|undefined;constructor(data?: ICar){if(data){for(varpropertyindata){if(data.hasOwnProperty(property))(<any>this)[property]=(<any>data)[property];}}}init(data?: any){if(data){this.name=data["Name"];this.manufacturer=data["Manufacturer"] ? Company.fromJS(data["Manufacturer"]) : <any>undefined;}}staticfromJS(data: any): Car{letresult=newCar();result.init(data);returnresult;}toJSON(data?: any){data=typeofdata==='object' ? data : {};data["Name"]=this.name;data["Manufacturer"]=this.manufacturer ? this.manufacturer.toJSON() : <any>undefined;returndata;}}exportinterfaceICar{name: string|undefined;manufacturer: Company|undefined;}exportclassPersonimplementsIPerson{firstName: string;middleName: string|undefined;lastName: string;gender: Gender;numberWithRange: number;birthday: Date;company: Company|undefined;cars: Car[]|undefined;constructor(data?: IPerson){if(data){for(varpropertyindata){if(data.hasOwnProperty(property))(<any>this)[property]=(<any>data)[property];}}}init(data?: any){if(data){this.firstName=data["FirstName"];this.middleName=data["MiddleName"];this.lastName=data["LastName"];this.gender=data["Gender"];this.numberWithRange=data["NumberWithRange"];this.birthday=data["Birthday"] ? newDate(data["Birthday"].toString()) : <any>undefined;this.company=data["Company"] ? Company.fromJS(data["Company"]) : <any>undefined;if(data["Cars"]&&data["Cars"].constructor===Array){this.cars=[];for(letitemofdata["Cars"])this.cars.push(Car.fromJS(item));}}}staticfromJS(data: any): Person{letresult=newPerson();result.init(data);returnresult;}toJSON(data?: any){data=typeofdata==='object' ? data : {};data["FirstName"]=this.firstName;data["MiddleName"]=this.middleName;data["LastName"]=this.lastName;data["Gender"]=this.gender;data["NumberWithRange"]=this.numberWithRange;data["Birthday"]=this.birthday ? this.birthday.toISOString() : <any>undefined;data["Company"]=this.company ? this.company.toJSON() : <any>undefined;if(this.cars&&this.cars.constructor===Array){data["Cars"]=[];for(letitemofthis.cars)data["Cars"].push(item.toJSON());}returndata;}}exportinterfaceIPerson{firstName: string;middleName: string|undefined;lastName: string;gender: Gender;numberWithRange: number;birthday: Date;company: Company|undefined;cars: Car[]|undefined;}The NJsonSchema.SampleJsonSchemaGenerator can be used to generate a JSON Schema from sample JSON data:
By default, the NJsonSchema.SampleJsonSchemaGenerator generates a JSON Schema based on the JSON Schema specification. See: JSON Schema Specification
vargenerator=newSampleJsonSchemaGenerator(newSampleJsonSchemaGeneratorSettings());varschema=generator.Generate("{...}");Input:
{
"int": 1,
"float": 340282346638528859811704183484516925440.0,
"str": "abc",
"bool": true,
"date": "2012-07-19",
"datetime": "2012-07-19 10:11:11",
"timespan": "10:11:11"
}Output:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"int": {
"type": "integer"
},
"float": {
"type": "number"
},
"str": {
"type": "string"
},
"bool": {
"type": "boolean"
},
"date": {
"type": "string",
"format": "date"
},
"datetime": {
"type": "string",
"format": "date-time"
},
"timespan": {
"type": "string",
"format": "duration"
}
}
}To generate a JSON Schema for OpenApi, provide the SchemaType.OpenApi3 in the settings. See: OpenApi Specification
vargenerator=newSampleJsonSchemaGenerator(newSampleJsonSchemaGeneratorSettings{SchemaType=SchemaType.OpenApi3});varschema=generator.Generate("{...}");Input:
{
"int": 12345,
"long": 1736347656630,
"float": 340282346638528859811704183484516925440.0,
"double": 340282346638528859811704183484516925440123456.0,
}Output:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"int": {
"type": "integer",
"format": "int32"
},
"long": {
"type": "integer",
"format": "int64"
},
"float": {
"type": "number",
"format": "float"
},
"double": {
"type": "number",
"format": "double"
}
}
}Applications which use the library:
- VisualJsonEditor, a JSON schema based file editor for Windows.
- NSwag: The Swagger API toolchain for .NET
- SigSpec for SignalR Core: Specification and code generator for SignalR Core.