C#
JSON Schema
code generation
programming
software development

Generate C classes from JSON Schema

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Generating C# classes from JSON Schema is a good way to remove hand-written DTO boilerplate, but the quality of the result depends on the generator and on how expressive the schema is. Simple object schemas usually map cleanly; advanced schema features such as oneOf, anyOf, or open-ended dictionaries often require manual review after generation.

What a Generator Actually Uses

A JSON Schema describes fields, required properties, nullability, arrays, enums, and nested objects. A C# generator reads that structure and turns it into classes, enums, and property types.

Example schema:

json
1{
2  "title": "Person",
3  "type": "object",
4  "properties": {
5    "id": { "type": "integer" },
6    "name": { "type": "string" },
7    "email": { "type": "string" }
8  },
9  "required": ["id", "name"]
10}

A reasonable C# result might look like:

csharp
1public class Person
2{
3    public int Id { get; set; }
4    public string Name { get; set; } = string.Empty;
5    public string? Email { get; set; }
6}

That is the main benefit: the schema becomes the source of truth instead of duplicated class definitions.

A Common Tooling Approach

One popular option in .NET projects is NJsonSchema. It can read a schema and generate C# code programmatically.

csharp
1using NJsonSchema;
2using NJsonSchema.CodeGeneration.CSharp;
3
4var schema = await JsonSchema.FromFileAsync("person.schema.json");
5var settings = new CSharpGeneratorSettings
6{
7    Namespace = "MyApp.Contracts"
8};
9
10var generator = new CSharpGenerator(schema, settings);
11string code = generator.GenerateFile();
12
13Console.WriteLine(code);

This is useful when generation is part of a build step or a contract-sync tool.

Things to Decide Before Generating

Schema-to-class generation is not only about syntax. You should decide:

  • Which serializer you use, such as System.Text.Json or Newtonsoft.Json
  • Whether nullable reference types are enabled
  • How enums should be represented
  • Whether generated files are committed or created during build

Those choices affect the generated code style and how much cleanup is needed later.

Where Generators Struggle

Not every JSON Schema concept maps neatly onto C# classes.

Tricky areas include:

  • 'oneOf and anyOf, which may require inheritance or custom converters'
  • Additional properties, which often map to dictionaries
  • Pattern-based properties, which do not have a direct static-class equivalent
  • Schema references split across many files

For those cases, generation should be treated as a starting point, not magic.

Make Generation Repeatable

If the schema belongs to an external API, generation should be reproducible. That usually means:

  • Keep the schema file in source control
  • Check in generator settings
  • Regenerate classes when the schema changes
  • Avoid editing generated files by hand

A common pattern is to place generated code in a dedicated folder and use partial classes if you need custom logic nearby.

This separation matters because generated transport objects tend to change with the schema, while domain behavior changes for business reasons. Keeping those concerns apart avoids unnecessary merge conflicts and regeneration pain.

Common Pitfalls

  • Assuming every JSON Schema feature has a perfect one-to-one mapping to C#.
  • Hand-editing generated files and then losing those edits on the next generation pass.
  • Forgetting serializer settings, nullability rules, or namespace layout before generation.
  • Treating generated DTOs like domain models instead of transport contracts.

Summary

  • JSON Schema can be converted into C# classes to reduce repetitive DTO work.
  • Simple object schemas generate cleanly; advanced schema features often need manual review.
  • Tools such as NJsonSchema can automate the process inside a .NET workflow.
  • Decide serializer, nullability, and generation strategy before adopting the tool.
  • Treat generated code as a contract artifact, not as a hand-maintained source file.

Course illustration
Course illustration

All Rights Reserved.