Skip to main content

JSON to C# Class — PascalCase Properties, JSON Attributes, Nullable, Zero Upload

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.
Examples:
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. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 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. 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. 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. 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.

Made by Toolora · 100% client-side · Updated 2026-05-29