JSON to C#
The result appears here.
Generate
Your document never leaves the browser.
C# records for System.Text.Json, from a JSON sample — in your browser.
Paste a payload and get C# types that System.Text.Json deserialises straight into. They target .NET 8, with nullable reference types switched on, so the compiler warns wherever a value may be missing. The whole file is one paste into your project, with its using directives included.
Every object becomes a sealed record with init-only properties, each carrying [JsonPropertyName] with its key, so the PascalCase names C# expects never change what is on the wire. A key present in every record is marked required, which makes the deserialiser reject a document that leaves it out.
The two line items show the difference. note is always there but sometimes null, so it is required string?: the key must be sent, and it may be null. gift-wrap is sometimes absent, so it is bool? without required. Keys present and never null keep plain types, such as long for qty and double for price.
The sample, an order with two line items, pasted as the source
{
"order_id": 1042,
"placed_at": "2026-09-25T10:15:00Z",
"paid": true,
"customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"items": [
{ "sku": "PEN-01", "qty": 2, "price": 3.5, "note": null },
{ "sku": "INK-07", "qty": 1, "price": 12, "note": "Fragile", "gift-wrap": true }
]
}The records written for it
// Generated by myjsoneditor.com for System.Text.Json (.NET 8).
#nullable enable
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Generated;
public sealed record Customer
{
[JsonPropertyName("name")]
public required string Name { get; init; }
[JsonPropertyName("email")]
public required string Email { get; init; }
}
public sealed record Item
{
[JsonPropertyName("sku")]
public required string Sku { get; init; }
[JsonPropertyName("qty")]
public required long Qty { get; init; }
[JsonPropertyName("price")]
public required double Price { get; init; }
[JsonPropertyName("note")]
public required string? Note { get; init; }
[JsonPropertyName("gift-wrap")]
public bool? GiftWrap { get; init; }
}
public sealed record Root
{
[JsonPropertyName("order_id")]
public required long OrderId { get; init; }
[JsonPropertyName("placed_at")]
public required string PlacedAt { get; init; }
[JsonPropertyName("paid")]
public required bool Paid { get; init; }
[JsonPropertyName("customer")]
public required Customer Customer { get; init; }
[JsonPropertyName("items")]
public required List<Item> Items { get; init; }
}An order id and a flag
{ "order_id": 1042, "paid": true }With Shape class and Namespace Shop
// Generated by myjsoneditor.com for System.Text.Json (.NET 8).
#nullable enable
using System.Text.Json.Serialization;
namespace Shop;
public sealed class Root
{
[JsonPropertyName("order_id")]
public required long OrderId { get; set; }
[JsonPropertyName("paid")]
public required bool Paid { get; set; }
}Option
Shape: record, the default, or class, which writes get; set; properties for code that mutates what it reads.
Option
Namespace: Generated by default, written as a file-scoped namespace declaration. Type your project’s own.
An integer beyond Int64 becomes a JsonElement, with a comment suggesting GetRawText() to read its digits exactly. A field whose type varies between records, or a list of mixed values, becomes JsonElement or List<JsonElement> too, with a comment naming the types that were seen.
Nested objects become records of their own, named after the keys that hold them, and the elements of a list take the singular, so items holds a List<Item>. Two objects with identical keys and types share a single record, wherever in the document each one was found. A key beginning with a digit gets an underscore, so 2fa is the property _2Fa. A list of objects uses List<T>; switch it to IReadOnlyList<T> or an array if your code prefers them, since System.Text.Json reads all three.
A 20-digit account number and a list of mixed values
{ "account": 12345678901234567890, "code": [1, "A"] }Both are JsonElement, with a comment naming what was seen
// Generated by myjsoneditor.com for System.Text.Json (.NET 8).
#nullable enable
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Generated;
public sealed record Root
{
[JsonPropertyName("account")]
public required JsonElement Account { get; init; } // integer past Int64 — read it with GetRawText()
[JsonPropertyName("code")]
public required List<JsonElement> Code { get; init; } // elements: one of: long, string
}Inference and code generation both run inside this browser tab. The sample is never uploaded, stored on a server or logged, because the page has no server to send it to, and once loaded it carries on working with the connection off.
The shapes do, but the attributes are System.Text.Json’s. Replace JsonPropertyName with JsonProperty from Newtonsoft to use them there.
The header names .NET 8. The records use C# 11 required members and nullable reference types, which that release supports out of the box.
JsonSerializer.Deserialize<Root>(json), with your root type in place of Root. A missing required key throws a JsonException naming it.