JSON to C# class or record — paste JSON, get PascalCase properties with System.Text.Json or Newtonsoft attributes, nested classes, nullable T?, init setters, DateTime detection.
- Runs locally
- Category Developer & DevOps
- Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
How types, attributes & nullability are inferred
Each JSON object becomes a named class or record with PascalCase properties. When the C# name differs from the wire key (snake_case, kebab-case, camelCase), a [JsonPropertyName] (System.Text.Json) or [JsonProperty] (Newtonsoft) attribute preserves the exact key so (de)serialisation round-trips — System.Text.Json is case-sensitive by default, so this attribute is what actually makes snake_case JSON bind. Integer numbers infer int (or long when they exceed Int32 range); fractional numbers infer double; a number that is sometimes whole and sometimes fractional widens to double. ISO-8601 strings infer DateTime when "Detect dates" is on. Arrays of objects fold into ONE class — keys missing from some elements (or seen as null) become nullable T?. A value that is only ever null types as object.
What this tool does
Paste any JSON payload — a GitHub API response, a Stripe webhook, an appsettings.json, a third-party REST body — and get back a clean set of C# `class` (or `record`) declarations with PascalCase properties, ready to drop into a `.cs` file. JSON keys are PascalCased into valid C# identifiers (`site_admin` → `SiteAdmin`, `is-active` → `IsActive`, `userId` → `UserId`); whenever the C# name differs from the wire key, the tool attaches a `[JsonPropertyName("site_admin")]` (System.Text.Json) or `[JsonProperty("site_admin")]` (Newtonsoft) attribute so (de)serialisation round-trips — System.Text.Json is case-sensitive by default, so this attribute is exactly what makes snake_case JSON bind. Numbers are split, not flattened: an integer that fits in Int32 infers `int`, a larger integer infers `long`, a fractional value infers `double`, and a field that is sometimes whole and sometimes fractional widens to `double`. ISO-8601 strings infer `DateTime` when "Detect dates" is on. Arrays of objects fold into ONE shared class, so `[{"a":1},{"a":1,"b":2}]` gives a single type with both fields, not two near-duplicates — and keys missing from some elements (or seen as null) become nullable `T?`. Toggle `class` vs `record`, `{ get; set; }` vs `{ get; init; }`, nullable on/off, rename the root class, share the input and root name as a link, then copy or download the `.cs` file. Only the `using` directives the output actually needs are emitted. Everything runs in your browser — the JSON never touches a server.
Tool details
- Input
- Files + Text + Numbers
- The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
- Output
- Live result + Copy + Download
- The result area focuses on usable output, with copy, download, or preview actions when supported.
- Privacy
- Browser-side processing
- The main tool logic does not call an external API, so inputs normally stay in the current tab.
- Save / share
- Shareable URL state
- Key settings are encoded in the URL so another person can reopen the same setup.
- Performance budget
- Initial JS <= 25 KB
- No WASM budget is declared, keeping the tool quick to open on mobile.
- Best fit
- Developer & DevOps · Developer
- Category and role tags drive related tools, internal links, and quick fit checks.
How to use
-
1. Input
Paste or drop your content into the tool panel.
-
2. Process
Click the button. All processing is local in your browser.
-
3. Copy / Download
Copy the result or download to disk in one click.
How JSON to C# Class fits into your work
Use it in the small gaps between coding, reviewing, debugging, and shipping.
Developer jobs
- Formatting, validating, shrinking, or inspecting code-adjacent text.
- Preparing snippets for documentation, tickets, commits, or handoff.
- Checking a small payload quickly without switching tools.
Developer checks
- Run irreversible transforms like minify or obfuscate on a copy.
- Keep secrets out of pasted snippets unless the tool explicitly stays local.
- Use your normal tests or linter before shipping transformed code.
Good next steps
These links move the current task into a more complete workflow.
- 1 JSON to TypeScript Interface JSON to TypeScript interface — paste JSON, get clean interfaces with union types from arrays, optional vs required detection, root name customizable. Open
- 2 JSON to Go Struct JSON to Go struct — paste JSON, get typed structs with json tags, exported fields, nested sub-structs, pointers for nullable, int64 and omitempty options. Open
- 3 JSON to Python Dataclass JSON to Python — paste JSON, get @dataclass or Pydantic v2 models with type hints, Optional inference, nested classes, snake_case fields and aliases. Open
Real-world use cases
Type a third-party API response without hand-writing classes
You're integrating the GitHub API and the user object has 30+ fields. Curl the endpoint once, paste the JSON here, set the root name to `GitHubUser`, keep System.Text.Json. The nested objects lift out as their own classes automatically (`GitHubUserPlan`), `html_url` becomes `HtmlUrl` with a `[JsonPropertyName("html_url")]` attribute, and `site_admin` becomes `SiteAdmin` so it actually binds. Copy the output into `Models/GitHubUser.cs` and `JsonSerializer.Deserialize<GitHubUser>(body)` fills a fully-typed object instead of a `JsonElement` you have to walk by hand.
Generate request/response DTOs for a new ASP.NET endpoint
A teammate sends you a sample JSON body for the `/orders` POST they're building. Paste it, name the root `CreateOrderRequest`, switch the type to `record` and the accessor to `init` so the DTO is immutable. Paste the response sample too as `CreateOrderResponse`. Two records, fully attributed, committed to `Dtos.cs` before either of you writes the controller action.
Decide nullable vs non-nullable for a webhook payload
A vendor's webhook sometimes includes `cancelled_at` and sometimes omits it. Log the first few payloads, paste them as a JSON array, and the optional-field detection flags `cancelled_at`. With nullable on and detect-dates on it becomes `DateTime?`, so in your handler `if (e.CancelledAt is not null)` cleanly distinguishes "cancelled" from "still active" — instead of guessing whether default(DateTime) means absent.
Replace a JObject / dynamic blob with a real type
Old code does `dynamic data = JObject.Parse(body)` and reaches in with `data.user.id`, losing all compile-time checking. Capture one representative response, paste it, generate the class, replace the dynamic. Now `int`, `long`, and `double` are inferred at the property level and the compiler catches a renamed field instead of a runtime `RuntimeBinderException` in production.
Build strongly-typed config from appsettings.json
Your service reads a `config.json` / `appsettings.json` section. Paste it, name the root `ServiceOptions`, get `ServiceOptions`, `ServiceOptionsServer`, `ServiceOptionsServerTls` nested classes with `int` ports and `bool` flags. Drop them in `ServiceOptions.cs`, bind with `builder.Services.Configure<ServiceOptions>(...)`, and your config is type-checked at compile time instead of throwing at runtime on a typo'd key.
Common pitfalls
Pasting a single object and expecting some properties to be nullable. A single object has no missing-key signal, so every field is required unless its value is literally null. Nullable/optional inference only kicks in across an array of objects where some elements carry a key and others don't. To explore optionality from one sample, wrap it as `[{...}]`.
Expecting System.Text.Json to bind snake_case without the attribute. Unlike Newtonsoft (case-insensitive by default), System.Text.Json matches property names case-sensitively. That's why this tool emits `[JsonPropertyName("site_admin")]` — delete it and `SiteAdmin` silently comes back as its default. Keep the attributes, or set a global naming policy in your serializer options.
Assuming numeric IDs should be long. If your IDs arrive as JSON strings (Stripe `cus_123`, many UUID APIs), they infer as `string`, not long — and that's correct. `long` only applies to integer JSON values that exceed Int32 range. Don't manually retype a string ID to long; you'll break deserialization with a format exception.
Treating a field that's only ever null as a typed property. `{"meta": null}` gives `public object Meta` because null carries no type information. If you know the real shape, feed a non-null sample (`{"meta": {"k": 1}}`) so the tool can infer a proper class.
Pasting JSON5 / JSON-with-comments / trailing commas. The tool uses strict `JSON.parse`, so comments, unquoted keys, and trailing commas all error out with a line and column. Strip them first, or run the input through a JSON formatter as a pre-step.
Privacy
Your JSON never leaves this browser tab. Parsing and type inference use the browser's built-in `JSON.parse`; there is no network call and no analytics on the textarea content. The Share link encodes your input and the root class name into the URL so a result is reproducible — that means YOU decide when to share. If the payload is sensitive (internal IDs, customer data, prod responses), copy the generated C# instead of sharing the link. Only your option choices (attribute style, class/record, init/set, nullable, detect-dates) are stored in localStorage so your preferred style persists across visits.
FAQ
Tool combos
Folks in your role tend to reach for these alongside this tool.
- Add Line Numbers Number every line of pasted text — set start, step and separator, zero-pad to align, skip blanks, or strip numbers back off — browser-only
- AES Text Encryptor Encrypt & decrypt text with a password — AES-256-GCM + PBKDF2 via WebCrypto — 100% in your browser, nothing uploaded
- Affine Cipher Encoder & Decoder Encrypt and decrypt the ax+b affine cipher with live modular-inverse check, browser-only
- Age Difference Calculator The exact gap between two birthdays — years/months/days, percentage, and the date one person is twice the other's age — browser-only