JSON to C# Class Generator

Generate C# class definitions from JSON with proper type inference, JsonPropertyName attributes, and nullable reference types.

What is JSON to C# Class Generator?

C# is a statically typed language where every JSON field must map to a named property on a class. The .NET ecosystem offers two main JSON libraries: System.Text.Json (built into .NET Core 3.0+ and .NET 5+) and Newtonsoft.Json (Json.NET). Both use attribute-based property mapping — [JsonPropertyName("key")] for System.Text.Json and [JsonProperty("key")] for Newtonsoft. Writing these classes by hand for a large API response requires careful PascalCase conversion (C# convention) and attribute placement for every property that has a different JSON key name. This generator automates the conversion: it infers C# types, converts JSON keys to PascalCase property names, adds [JsonPropertyName] attributes when the names differ, marks value types as nullable (int?, double?) when the JSON contains null, and detects ISO-8601 strings as DateTime or DateTimeOffset. The output is compatible with System.Text.Json out of the box.

How to Use

  1. Set the root class name (e.g. "ApiResponse", "OrderDetail") — this becomes the outermost C# class
  2. Enable "Nullable types" for C# 8.0+ projects — value types (int, double, bool, DateTime) become int?, double? etc. for fields that can be null in the JSON
  3. Enable "System.Text.Json attributes" to add [JsonPropertyName("originalKey")] on properties whose PascalCase name differs from the JSON key — required for correct deserialization
  4. Enable "Detect dates" to map ISO-8601 strings to DateTime instead of string — use this with JsonSerializerOptions.Converters if you need DateTimeOffset or custom formats
  5. Paste your JSON and click "Generate C# Classes" — the output is ready to paste into a .cs file

Why Use This Tool?

Generates C# 8.0+ compatible classes with { get; set; } auto-properties — no backing fields needed
[JsonPropertyName] attributes bridge camelCase JSON keys and PascalCase C# properties automatically
Nullable reference type support (string? vs string) for C# 8.0 nullable context
Nested classes are ordered children-first so the file compiles without forward declarations
Compatible with both System.Text.Json (.NET 5+) and Newtonsoft.Json (Json.NET) — attributes differ but the property structure is the same
Runs entirely in the browser — your API response data never leaves your device

Tips & Best Practices

  • For Newtonsoft.Json, replace [JsonPropertyName("key")] with [JsonProperty("key")] — everything else in the generated output is identical
  • C# records (record class UserProfile(string Id, string Name)) are a cleaner alternative to classes for read-only API responses in .NET 5+ — the generated class properties can be directly converted to record positional parameters
  • Add [JsonIgnoreProperties(ignoreUnknown = true)] in Newtonsoft.Json or set JsonSerializerOptions.DefaultIgnoreCondition for System.Text.Json to handle new API fields gracefully in production
  • For ASP.NET Core Web API, the generated classes work directly as [FromBody] request parameters and return types — the framework's JSON pipeline handles serialization automatically
  • C# 10+ allows record structs (readonly record struct) for small, frequently copied value objects — suitable for simple nested objects like Address or Coordinates

Frequently Asked Questions

What is the complete JSON type → C# type mapping?

JSON string → string (or DateTime/DateTimeOffset with date detection). JSON integer → int (or long for values > int.MaxValue). JSON float → double. JSON boolean → bool. JSON null → T? where T is the nullable version of the inferred type. JSON array → List<T> with T inferred from the first element. JSON object → a separate named class. Heterogeneous arrays → List<object>.

When should I use System.Text.Json vs Newtonsoft.Json?

Use System.Text.Json for new .NET 5+ projects — it is built into the platform, faster, and allocation-friendly. Use Newtonsoft.Json when: migrating existing code that depends on Json.NET behaviors, you need features not in System.Text.Json (JsonConverter for complex cases, dynamic deserialization, circular reference handling), or you target .NET Framework. The generated class structure is the same; only the attribute names differ.

What do nullable reference types (string?) mean in C# 8.0+?

C# 8.0 introduced a nullable annotation context. In this context, string means "never null" and string? means "can be null". The compiler warns you if you use a string? value without a null check. For JSON deserialization, fields that can be absent or null in the API response should be string?, while required fields should be string. This generator marks nullable based on null values observed in the sample data.

When should I use records instead of classes?

C# records (introduced in C# 9) are ideal for immutable API response models. record class ApiResponse(string Id, string Name) {...} provides value-based equality, a concise constructor, and with-expression syntax for non-destructive updates. They are a better default than mutable classes with { get; set; } properties for data transfer objects. Use classes when: the object is mutable (e.g. a form model), you need inheritance, or you need compatibility with older .NET versions.

Is my data sent to a server?

No. All code generation runs entirely in your browser. Your JSON data never leaves your device.

Real-world Examples

Deserializing a Microsoft Graph API user response

The Microsoft Graph API returns camelCase JSON. The generated C# class with [JsonPropertyName] attributes handles the PascalCase conversion automatically. The @odata.type field (which is a valid JSON key but an invalid C# identifier) gets a renamed property.

Input
{
  "id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
  "displayName": "Adele Vance",
  "mail": "[email protected]",
  "userPrincipalName": "[email protected]",
  "jobTitle": "Product Marketing Manager",
  "officeLocation": "18/2111",
  "mobilePhone": null,
  "createdDateTime": "2019-03-15T08:00:00Z"
}
Output
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

public class GraphUser
{
    [JsonPropertyName("id")]
    public string Id { get; set; }

    [JsonPropertyName("displayName")]
    public string DisplayName { get; set; }

    [JsonPropertyName("mail")]
    public string Mail { get; set; }

    [JsonPropertyName("userPrincipalName")]
    public string UserPrincipalName { get; set; }

    [JsonPropertyName("jobTitle")]
    public string JobTitle { get; set; }

    [JsonPropertyName("officeLocation")]
    public string OfficeLocation { get; set; }

    [JsonPropertyName("mobilePhone")]
    public string? MobilePhone { get; set; }

    [JsonPropertyName("createdDateTime")]
    public DateTime CreatedDateTime { get; set; }
}

Nullable nested address in an e-commerce order

Orders can exist without a billing address when created via API before checkout completes. The nullable Address? property allows the controller to check for null rather than comparing against a default-valued object.

Input
{
  "orderId": "ord-9921",
  "totalAmount": 199.95,
  "currency": "USD",
  "isPaid": false,
  "billingAddress": null,
  "lineItems": [
    { "sku": "ITEM-001", "quantity": 2, "unitPrice": 99.95 }
  ]
}
Output
using System.Collections.Generic;
using System.Text.Json.Serialization;

public class LineItem
{
    [JsonPropertyName("sku")]
    public string Sku { get; set; }

    [JsonPropertyName("quantity")]
    public int Quantity { get; set; }

    [JsonPropertyName("unitPrice")]
    public double UnitPrice { get; set; }
}

public class BillingAddress { }

public class Order
{
    [JsonPropertyName("orderId")]
    public string OrderId { get; set; }

    [JsonPropertyName("totalAmount")]
    public double TotalAmount { get; set; }

    [JsonPropertyName("currency")]
    public string Currency { get; set; }

    [JsonPropertyName("isPaid")]
    public bool IsPaid { get; set; }

    [JsonPropertyName("billingAddress")]
    public BillingAddress? BillingAddress { get; set; }

    [JsonPropertyName("lineItems")]
    public List<LineItem> LineItems { get; set; }
}

Related Tools