JSON to C# Class

Generate C# records or classes from JSON, with System.Text.Json attributes

Runs entirely in your browser. Your data never leaves this device.

Input · JSON
Output · C#

How to use it

  1. Paste a JSON object or array into the input panel.
  2. Choose record or class, then adjust nullability, type detection and the serializer.
  3. Copy the generated types straight into your project.

What the generator decides for you

Turning JSON into C# is mostly a series of small judgement calls, and this is what this tool picks.

Numbers. An integer becomes int, or long when it exceeds int.MaxValue. A number with a fractional part becomes double, or decimal if you ask for it. This is a genuine guess: JSON has exactly one number type, so 1 and 1.0 are indistinguishable in the payload even though they are different C# types. If a field is sometimes fractional, the sample you paste may not show it.

Strings that are not really strings. With detection enabled, a value matching the GUID format becomes Guid, and an ISO 8601 timestamp becomes DateTimeOffset — preferred over DateTime because it keeps the offset rather than silently reinterpreting it in local time.

Names. display_name becomes DisplayName with a [JsonPropertyName("display_name")] attribute. The attribute is only emitted when the C# name differs from the JSON name, so PascalCase payloads produce clean, attribute-free types. Names colliding with C# keywords get the @ prefix.

Shape merging. Two objects with identical keys and types become one type rather than two identical ones. This is what keeps output from a large payload readable.

Nullable reference types are the part people get wrong

With <Nullable>enable</Nullable> — the default in new .NET projects — the compiler tracks which references may be null. Deserializers ignore that entirely.

System.Text.Json will happily leave a non-nullable string Name { get; init; } as null if the JSON omits the property or sets it to null. The compiler thought it was guaranteed; at runtime it is not. You then get a NullReferenceException far from the cause, in code the compiler told you was safe.

Two honest options: mark properties string? and handle absence explicitly, or keep them non-nullable and validate immediately after deserialization. Silently initialising to string.Empty — which this generator does when you turn nullability off — hides missing data rather than surfacing it. Pick deliberately.

System.Text.Json versus Newtonsoft.Json

System.Text.Json is the default in modern .NET: faster, allocation-light, built in. Its strictness catches people migrating — it is case-sensitive unless configured otherwise, rejects trailing commas and comments by default, and will not coerce a JSON string into a number.

Newtonsoft.Json remains the pragmatic choice when you need TypeNameHandling, JsonConverter behaviour that has no modern equivalent, or a large existing codebase that relies on its permissive defaults. Switch the serializer option above and the attributes change from JsonPropertyName to JsonProperty accordingly.

Generated code is a starting point

Treat the output as scaffolding, not as a finished model. A generator sees one payload; it cannot know which fields are optional, which strings are really enums, which lists are never empty, or which double should have been decimal. Paste it in, then tighten the types against the API's actual documentation.

Frequently asked questions

Should I generate records or classes?

Records for DTOs you deserialize and never mutate — they are concise and give value equality. Classes when the object is mutated after construction or when a framework requires a parameterless constructor and settable properties.

Why are string properties nullable?

Because deserialization can produce null for any reference type regardless of what the JSON contained. With nullable reference types on, marking them `string?` reflects reality; the alternative is a non-null property that is null at runtime.

Does System.Text.Json match property names automatically?

It matches case-insensitively by default in ASP.NET Core, so `display_name` will not bind to `DisplayName` — snake_case needs either an explicit attribute or a naming policy. This generator emits the attribute, which works everywhere.

Why did two objects become one type?

Objects with identical shapes are merged into a single type. It keeps the output small and usually matches intent — a list of items should not produce one class per item.

What happens with an array of mixed types?

It becomes `List<object>`. There is no single C# type that fits, and guessing would produce code that fails at runtime rather than at compile time.

Should I use decimal for money?

Yes. Enable the decimal option for any monetary value — binary floating point cannot represent 0.1 exactly, and rounding errors accumulate. Note that JSON itself has no decimal type, so precision may already be lost upstream.

Related tools

browse category →

Last updated: