JSON to C# Class/Record Generator
Convert JSON to C# classes or records, with nullable reference types and System.Text.Json or Newtonsoft.Json attribute options.
What this tool generates
Paste a JSON payload and get ready-to-use C# class or record types with correctly inferred properties — nested objects become nested types, arrays of objects become List<T> of a generated item type, and you control whether reference-type properties are nullable and which JSON library's attributes get emitted. It runs entirely within your active Blazor Server session: your JSON is processed in-memory as part of this page's live connection and is never sent to a separate API, written to disk, or logged. Need to go the other direction — from an existing C# class to a sample JSON payload? See the C# to JSON Sample Generator, the reverse of this tool. Starting from XML instead of JSON? The XML to C# Class Generator does the same inference from an XML document. Working from a database schema instead? See the SQL Table to C# Entity Generator, which maps a CREATE TABLE script to C# entity classes.
Worked example
With the default options (classes, no nullable reference types, no attributes), this JSON:
{
"user_id": 42,
"user_name": "devtoolshub",
"is_active": true,
"tags": ["blazor", ".net"],
"address": {
"city": "Bengaluru"
}
}
generates:
public class Root
{
public int UserId { get; set; }
public string UserName { get; set; }
public bool IsActive { get; set; }
public List<string> Tags { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string City { get; set; }
}
Notice user_id → UserId (an int, correctly inferred), tags → a List<string>, and the nested address object becoming its own Address class referenced from Root. Turning on Records changes only the class/record keyword on both types; turning on System.Text.Json attributes adds a [JsonPropertyName("user_id")]-style attribute above every property, since none of these JSON keys match their generated C# name byte-for-byte.
Common errors when generating C# from JSON
| Error / behavior | Cause | Fix |
|---|---|---|
| "JSON payload is empty." | Input is blank, whitespace-only, or the literal null | Paste a real JSON object as the root value |
| "Invalid JSON: ..." | Malformed syntax — the underlying System.Text.Json parser rejected it | Fix the JSON first, or run it through the JSON Formatter, which reports the exact line and column |
| Generated class has no properties at all | The root of your JSON is an array ([ {...}, {...} ]), not an object — this generator only reads properties from an object root | Wrap the array in an object first, e.g. { "items": [ ... ] } |
| Two nested objects end up sharing one generated class | Both were inferred from a JSON key with the same name (e.g. two different "address" objects at different nesting levels) — only the first shape encountered is built | Rename one of the JSON keys before generating, or split the output into two classes by hand afterward |
Records vs classes for JSON models
A C# record gives you value-based equality and a concise ToString() for free — two records with identical property values are considered equal, which is often exactly what you want for a data-transfer object. A class is the more traditional choice and is still the right call when you plan to add mutable behavior, inheritance beyond simple data shape, or when working in a codebase that hasn't adopted records yet. Both System.Text.Json and Newtonsoft.Json deserialize into either shape correctly as long as the properties have public getters and setters, which is what this generator produces for both options — so switching between them later is a one-line change to the type keyword.
Nullable reference types: what actually gets a "?"
C#'s nullable reference types (NRT) feature only applies to reference types — string, List<T>, and nested class/record types. It does not apply to value types like int, bool, or decimal, which already have their own separate nullable form (int?) unrelated to the NRT feature. When you enable "Nullable reference types" here, this generator adds ? only to string, List<T>, and nested-type properties — value-typed properties are left exactly as inferred. If your project has <Nullable>enable</Nullable> in its .csproj, turn this on so the generated code doesn't produce nullability warnings the first time you build.
System.Text.Json vs Newtonsoft.Json attributes
When a JSON field name doesn't match C# PascalCase convention (for example user_id instead of UserId), you need an attribute to tell the serializer how to map between them. Pick System.Text.Json for modern .NET projects (5 and later, built into the runtime) — it emits [JsonPropertyName("user_id")]. Pick Newtonsoft.Json for older codebases still using Json.NET — it emits [JsonProperty("user_id")]. Properties whose name already matches the JSON key exactly get no attribute either way, since none is needed.
| Aspect | System.Text.Json | Newtonsoft.Json |
|---|---|---|
| Rename attribute | [JsonPropertyName("user_id")] | [JsonProperty("user_id")] |
| Namespace | System.Text.Json.Serialization | Newtonsoft.Json |
| Built into the .NET runtime? | Yes — since .NET Core 3.0 | No — separate NuGet package (Newtonsoft.Json) |
| ASP.NET Core default casing | camelCase — AddControllers() registers JsonNamingPolicy.CamelCase by default | PascalCase preserved unless you configure a naming strategy |
| Property name already matches JSON key | No attribute needed | No attribute needed |
How to use this tool
- Paste a sample JSON payload into the input editor.
- Set the root type name, choose records or classes, toggle nullable reference types, and pick an attribute style.
- Click Generate.
- Copy the output and adjust type names — nested arrays of objects are named
<Field>Item(for exampleTagsItem), since this generator doesn't attempt to singularize plural field names.
One gap worth knowing: large integers
Whole numbers are generated as int when they fit, long when they exceed int.MaxValue (2,147,483,647), and decimal only beyond long's range. Numbers containing a decimal point are always generated as decimal, not double — a deliberate choice that favors exact precision for typical API payloads, but review it if your source data is genuinely floating-point (scientific measurements, for example) rather than fixed-precision.
JSON input
{
"id": 1,
"user_name": "devtoolshub",
"tags": ["blazor", ".net"]
}Generated C#
C# output