JSON to C#
Generate C# records with JsonPropertyName attributes from a JSON sample for System.Text.Json.
JSON input
Generated code
Enter JSON on the left to generate a type from it.
What is JSON to C#?
A JSON to C# converter turns a sample JSON payload into C# record declarations ready to deserialize with System.Text.Json, the serializer built into modern .NET. Records with init-only properties are the current idiomatic way to model an API response: the object is immutable once constructed, value equality comes for free, and the serializer can populate it directly. The generated output also carries a [JsonPropertyName] attribute on every property, which is what makes the mapping reliable — C# convention capitalises property names while JSON keys are typically camelCase or snake_case, and relying on the serializer's naming policy to bridge that gap is a frequent source of properties that silently deserialize as null. Every property name is converted to PascalCase regardless of the source key's casing — camelCase, snake_case, or kebab-case all become the same PascalCase form the language expects — while the original wire key survives only in the attribute. A JSON number with a decimal point is typed as `double`, matching how System.Text.Json itself treats an untyped JSON number, rather than `float` or `decimal`.
How to use JSON to C#
- Paste a representative JSON response into the left panel — the generated properties match exactly the keys present in that sample.
- Set a root record name above the output (defaults to "Root"); each nested object becomes its own record named after the key holding it.
- Copy the records into your project and deserialize with JsonSerializer.Deserialize<Root>(json).
- Use the language picker above the output to emit the same shape as a Java record or Kotlin data class instead.
Examples
Flat object with JsonPropertyName attributes
Input
{"id": 1, "name": "Ada"}
Output
using System.Text.Json.Serialization; public record Root { [JsonPropertyName("id")] public int Id { get; init; } [JsonPropertyName("name")] public string Name { get; init; } }
Nested object becomes its own record
Input
{"user": {"id": 1, "roles": ["admin"]}}
Output
using System.Text.Json.Serialization; using System.Collections.Generic; public record User { [JsonPropertyName("id")] public int Id { get; init; } [JsonPropertyName("roles")] public List<string> Roles { get; init; } } public record Root { [JsonPropertyName("user")] public User User { get; init; } }
Decimal value becomes double
Input
{"id": 1, "price": 9.99}
Output
using System.Text.Json.Serialization; public record Root { [JsonPropertyName("id")] public int Id { get; init; } [JsonPropertyName("price")] public double Price { get; init; } }
Common mistakes
- Renaming a C# property without updating its [JsonPropertyName] — the serializer then finds no matching key and leaves the property at its default, with no exception to point at the cause.
- Assuming a camelCase naming policy covers the whole payload, which breaks the moment one key uses a different convention and produces nulls that look like an API problem rather than a mapping one.
- Leaving non-nullable reference types on fields the API may omit, which either triggers compiler warnings or yields a null in a property the type system claims can't be null.
- Leaving a monetary field typed as the generated double — swap it for decimal by hand when precision matters, since the generator has no way to know a number represents currency.
- Expecting a snake_case or kebab-case key to survive as the C# property name — every property is converted to PascalCase for you, and the original key only survives inside the [JsonPropertyName] attribute.
Why use this tool
- Emits explicit [JsonPropertyName] attributes, avoiding the naming-policy mismatches that silently null out properties.
- Adds the required using directives, including System.Collections.Generic when the payload contains arrays.
- Runs entirely client-side — a production API response pasted as a sample for record generation never reaches a server.
- Converts every property name to PascalCase automatically regardless of the source key's casing, while keeping the original wire key intact via [JsonPropertyName] for the serializer.
- Infers int vs. double per value from the sample instead of defaulting every JSON number to one imprecise numeric type.