Tools and Demo Based on Existing .NET JSON Schema Components
While there are variety of JSON schema tools since the introduction of JSON schema, this project is focused on the following:
- Existing .NET (Framework) components that can generate JSON schema from POCO classes or generate POCO classes from JSON Schema.
- Introduce locally run tools.
- Develop CLI tools for transforming POCO to JSON schema.
- Compare with different components of generating JSON schema.
If a .NET developer who prefer code first approach, you would often create POCO classes first for various purposes, and generate meta data like XML schema, JSON schema, database schema, WSDL and Swagger/OpenAPI definition. The goal of these project is to find the "best" .NET component that can generate JSON schema from a complex POCO class, and the schema can make the hand-crafting of JSON data become convenient with a decent text editor like Visual Studio Code and alike, fully utilizing the data constraints defined in the data model.
Validation Tools
Visual Studio
References:
Visual Studio Code
References:
From Schema to C# Codes
Visual Studio
Go "Main Menu -> Edit -> Paste Special -> Paste JSON as Classes".
Generating Schema From C#
Plain Old Classes can provide enough info for XML schema and JSON schema. This open source project provides side by side comparisons of some popular components of generating schema from a POCO class.
JsonSchemaComponents provides 4 CLI tools utilizing 4 JSON schema components, so you can choose the right one after comparing their outputs.
GenerateJsonSchema.exe using .NET 9 Extract SChema
Usage:
GenerateJsonSchema.exe
Generate JSON Schema from a POCO class.
JSON Schema Generator version 1.0
Fonlow (c) 2025
/ClassName, /C Class name including namespace, e.g., /C=My.Namespace.MyClass
/ClassFile, /CF Class file path in C# or VB.NET, e.g., /CF=c:/myCsharpClass.cs
/AssemblyFile, /A Assembly file name including file extension. e.g., /A=abc.dll
/OutputPath, /OP File path of the JSON schema output. e.g., /OP=c:/temp/MyJsonSchema.json
/Title, /T Title of schema. e.g., /t='CodeGen meta of WebApiClientGen'
/Description, /D Description of schema. e.g., /d 'Post to CodeGen controller of Web API'
/Help, /h, /? Shows this help text
Example:
GenerateJsonSchema.exe /op=c:/temp/demoSchema.json /c=Fonlow.CodeDom.Web.CodeGenSettings /a=DataModels.dll
Hints:
- The other CLI apps have the same set of arguments.
GenerateSchemaWithNJsonSchema.exe using NJsonSchema
GenerateSchemaWithNewtonSoft.exe using NewtonSoft.Json
Online validator on: https://www.jsonschemavalidator.net/ which can validate draft v3 to 2020-12.
GenerateSchemaWithJsonSchemaNet.exe using JSON Everything
Online validator on: https://json-everything.net/json-schema for Draft 6 to 2020-12
Comparison of .NET Components of Generating JSON schema from POCO.
The JSON data is CodeGen.json that is the CodeGen definition of WebApiClientGen, and the schemas are those generated by various .NET components.
The POCO classes are defined in DataModels/Models.cs:
...
public class CodeGenSettingsBase
{
[Required]
[JsonRequired]
[Description("Cherry picking of data models and API controllers.")]
public required CodeGenConfig ApiSelections { get; set; }
}
/// <summary>
/// What CodeGenController is expecting
/// </summary>
public class CodeGenSettings : CodeGenSettingsBase
{
[Required]
[JsonRequired]
[Description("Options of output")]
public required CodeGenOutputs ClientApiOutputs { get; set; }
}
/// <summary>
/// For cherry picking APIs and data models
/// </summary>
public class CodeGenConfig
{
/// <summary>
/// To exclude some controllers. For example, [My.Namespace.Home, My.Namespace.FileUpload] for My.Namespace.HomeController and My.Namespace.FileUploadController.
/// </summary>
public string[] ExcludedControllerNames { get; set; }
string[] dataModelAssemblyNames;
/// <summary>
/// To include assemblies containing data models. Assembly names should be without file extension.
/// An assembly should appear in either DataModelAssemblyNames or DataModels, not both.
/// If the Web API assembly is also included, it should be behind those data model assemblies that it depends on.
/// </summary>
[Description("Exclusive to DataModels.")]
public string[] DataModelAssemblyNames
{
get { return dataModelAssemblyNames; }
set
{
dataModelAssemblyNames = value;
AllDataModelAssemblyNames = this.GetAllDataModelAssemblyNames();
}
}
DataModel[] dataModels;
...
The comparison is done through the following:
- The JSOn file has a reference to the schema file, and display and edit the JSON data in Visual Studio Code
- Online validator on: https://www.jsonschemavalidator.net/
- Online validator on: https://jsonschema.dev/
.NET 9 Extract SChema
{
"type": [
"object",
"null"
],
"properties": {
"ClientApiOutputs": {
"type": [
"object",
"null"
],
"properties": {
"ClientLibraryProjectFolderName": {
"type": [
"string",
"null"
]
},
"FileName": {
"type": [
"string",
"null"
]
},
"GenerateBothAsyncAndSync": {
"type": "boolean"
},
By default:
- All string fields are nullable and can be absent, unless required.
- All value type fields can be absent and must have a value, unless nullable, unless required.
Nullable Value Type
"StringAsString": {
"type": "boolean"
},
"CamelCase": {
"type": [
"boolean",
"null"
]
},
For Required Field
It honours JsonRequiredAttribute of .NET, and create the following:
"properties": {
"AssemblyName": {
"type": [
"string",
"null"
]
},
},
"required": [
"AssemblyName"
]
Remarks:
- Visual Studio Code does not care about the missing required field.
- Visual Studio cares and enforces. For new entry, only after inputting the required fields, the optional fields will appear in intellisense.
- https://www.jsonschemavalidator.net/ pick the missing field.
For Enum Field
"CherryPickingMethods": {
"type": [
"integer",
"null"
]
},
Overall it is good.
NJsonSchema
It declares schema version and a default title. And both VS and VS Code are not working well with the draft-04 schema, keeping saying whatever property not allowed.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "CodeGen Meta of WebApiClientGen",
"description": "POST to CodeGen controller",
"definitions": {
"CodeGenOutputs": {
"allOf": [
{
"$ref": "#/definitions/ModelGenOutputs"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"ClientLibraryProjectFolderName": {
"type": [
"null",
"string"
]
},
"FileName": {
"type": [
"null",
"string"
]
},
"GenerateBothAsyncAndSync": {
"type": [
"boolean",
"null"
]
},
For Required Field
It respects RequiredAttribute but not others like JsonRequiredAttribute.
For Enum fields
"CherryPickingMethods": {
"type": "integer",
"description": "",
"x-enumFlags": true,
"x-enumNames": [
"All",
"DataContract",
"NewtonsoftJson",
"Serializable",
"AspNet",
"NetCore",
"ApiOnly"
],
"enum": [
0,
1,
2,
4,
8,
16,
32
]
}
While there is "x-enumFlags": true
as mentioned on flagged enum (bitwise), JSON Schema standard body apparently hasn't reach and aggrement, according to https://github.com/json-schema-org/json-schema-vocabularies/issues/24. Not sure which editor will respect this?
Nullable boolean and Alike
"StringAsString": {
"type": "boolean"
},
"CamelCase": {
"type": [
"boolean",
"null"
]
},
NewtonSoft.Json
{
"title": "CodeGen Meta of WebApiClientGen",
"description": "POST to CodeGen controller",
"definitions": {
"CodeGenConfig": {
"description": "Cherry picking of data models and API controllers.",
"type": "object",
"properties": {
"ExcludedControllerNames": {
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
},
"DataModelAssemblyNames": {
"description": "Exclusive to DataModels.",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
},
"DataModels": {
"description": "Exclusive to DataModelAssemblyNames",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/DataModel"
}
},
Therefore:
- https://www.jsonschemavalidator.net/ reports 5 errors
- https://jsonschema.dev/ reports 26 errors, however, this validator is "The home of JSON Schema validation right in your browser 🚧 Alpha 🚧 draft-7 only"
For Required Field
It honours JsonRequiredAttribute and RequiredAttribute, but not DataMember(IsRequired = true)
and not the required
keyword, and generate the following:
"AssemblyName": {
"type": "string"
},
Remarks:
- In Visual Studio Code, giving it null the editor won't complain.
- Visual Studio can pick the invalid null value.
- https://www.jsonschemavalidator.net/ pick the missing field, and the invalid null value.
However, all other sibling fields are required by default:
"required": [
"AssemblyName",
"TargetDir",
"TSFile",
"ContentType",
"AsModule",
"ClientNamespaceSuffix",
"ContainerNameSuffix",
"DataAnnotationsToComments",
"HelpStrictMode",
"NgDateOnlyFormControlEnabled"
]
To avoid, need to do this:
JSchemaGenerator generator = new JSchemaGenerator();
generator.DefaultRequired = Required.Default;
For enum field
"CherryPickingMethods": {
"type": [
"integer",
"null"
]
},
Nullable boolean and Alike
"StringAsString": {
"type": "boolean"
},
"CamelCase": {
"type": [
"boolean",
"null"
]
},
JSON Everything
Online validator on: https://jsonschema.net/
{
"title": "CodeGen Meta of WebApiClientGen",
"description": "POST to CodeGen controller",
"type": "object",
"properties": {
"ApiSelections": {
"type": "object",
"properties": {
"ExcludedControllerNames": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"DataModelAssemblyNames": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"DataModels": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"AssemblyName": {
"type": "string"
},
"CherryPickingMethods": {
"enum": [
"All",
"DataContract",
"NewtonsoftJson",
"Serializable",
"AspNet",
"NetCore",
"ApiOnly",
null
]
},
Nullable boolean and alike
"StringAsString": {
"type": "boolean"
},
"CamelCase": {
"type": [
"boolean",
"null"
]
},
For enum Field
"CherryPickingMethods": {
"enum": [
"All",
"DataContract",
"NewtonsoftJson",
"Serializable",
"AspNet",
"NetCore",
"ApiOnly",
null
]
},
However, this is unfriendly to flagged enum and int.
For Required Field
It does not care about JsonRequiredAttribute and RequiredAttribute, while respecting the "required" keyword of C#.
Summary
For nullable boolean and alike, all can generate correct codes allowing null.
Some schemas generated declares Schema Identification, while others don't by default.
NJsonSchema uses literal enum and int, seemly supports flagged enum, but a good editor respecting this is not yet found.
JSON Everything exports literal enum. Not good.
NewtonJson and NJsonSchema can read what declared in DescriptionAttribute
and make it become the Description field of the schema, while Visual Studio Code displays Description.
.NET 9 Schema Export does not support Title and Description.
So, basically for my cases, particularly for the CodeGen settings, I can use only what exported by .NET 9 or NewtonSoft JSON Schema.
So the verdict is, Newtonsoft.Json.Schema.Generation
is the best, at least for my cases. .NET 9 Schema Export is the 2nd best.
Top comments (0)