C# classes and record types define typed data models in .NET. Learn how System.Text.Json, Newtonsoft.Json, attributes, and records enable robust JSON serialization.
A C# Class is the fundamental reference type blueprint in the C# (.NET) programming language used to encapsulate data state, methods, events, and business logic. Starting with C# 9, .NET also introduced Record Types (record class and record struct), which provide value-based equality semantics, compiler-synthesized copy constructors (with expressions), and concise syntax tailored specifically for immutable data-transfer objects (DTOs) and API payloads.
When building web APIs, microservices, cloud applications, or desktop clients in .NET, developers serialize and deserialize JSON using either the high-performance built-in System.Text.Json namespace or the legacy Newtonsoft.Json (Json.NET) library. By decorating C# classes and records with serialization attributes like [JsonPropertyName("field_name")] or [JsonProperty("field_name")], developers map external JSON key formats (such as snake_case or camelCase) directly into idiomatic PascalCase C# properties.
Instantly convert any JSON payload into strongly typed C# class or record definitions with our JSON to C# Class Converter, or generate models for other language runtimes with JSON to TypeScript, JSON to Go, and JSON to Rust.
| Specification | Details |
|---|---|
| Language & Runtime | C# (C# 8.0 through C# 13.0+) on .NET 6, 7, 8, and 9 |
| Primary Serializer | System.Text.Json (high throughput, zero allocation UTF-8 processing, built into .NET BCL) |
| Legacy Serializer | Newtonsoft.Json (Json.NET — rich feature set, classic .NET Framework standard) |
| Field Mapping Attributes | [JsonPropertyName("key")] (System.Text.Json), [JsonProperty("key")] (Newtonsoft.Json) |
| Data Model Paradigms | Mutable class ({ get; set; }) vs Immutable record ({ get; init; }) |
| Nullability Model | C# 8+ Nullable Reference Types (#nullable enable) with T? annotations |
| Collection Types | List<T>, IReadOnlyList<T>, T[], HashSet<T>, Dictionary<string, T> |
| Date & Time Types | DateTime, DateTimeOffset (ISO-8601 with timezone offset), DateOnly, TimeOnly |
| Polymorphic Serialization | [JsonPolymorphic], [JsonDerivedType(typeof(Derived), typeDiscriminator: "type")] (.NET 7+) |
| Custom Conversions | Subclassing JsonConverter<T> with Read and Write override methods |
System.Text.Json with PascalCase Mapping & Nullable Reference TypesSystem.Text.Json is designed from the ground up for high throughput and minimal memory allocations by operating directly on ReadOnlySpan<byte> UTF-8 streams.
#nullable enable
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace App.Models
{
public class UserProfile
{
[JsonPropertyName("id")]
public long Id { get; set; }
[JsonPropertyName("username")]
public string Username { get; set; } = string.Empty;
[JsonPropertyName("email")]
public string Email { get; set; } = string.Empty;
[JsonPropertyName("is_active")]
public bool IsActive { get; set; }
[JsonPropertyName("bio")]
public string? Bio { get; set; }
[JsonPropertyName("created_at")]
public DateTime CreatedAt { get; set; }
[JsonPropertyName("roles")]
public List<string> Roles { get; set; } = new();
}
}
Records enforce immutability after object initialization, preventing accidental state mutations across application layers:
#nullable enable
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
public record OrderSummary
{
[JsonPropertyName("order_id")]
public string OrderId { get; init; } = string.Empty;
[JsonPropertyName("total_amount")]
public double TotalAmount { get; init; }
[JsonPropertyName("currency")]
public string Currency { get; init; } = "USD";
[JsonPropertyName("line_items")]
public List<OrderLineItem> LineItems { get; init; } = new();
}
public record OrderLineItem
{
[JsonPropertyName("sku")]
public string Sku { get; init; } = string.Empty;
[JsonPropertyName("quantity")]
public int Quantity { get; init; }
[JsonPropertyName("unit_price")]
public double UnitPrice { get; init; }
}
System.Text.Json.JsonSerializerusing System;
using System.Text.Json;
public class Program
{
public static void Main()
{
string rawJson = """
{
"order_id": "ORD-2026-X9",
"total_amount": 249.50,
"currency": "USD",
"line_items": [
{ "sku": "KEYBOARD-MECH", "quantity": 1, "unit_price": 199.50 },
{ "sku": "USB-C-CABLE", "quantity": 2, "unit_price": 25.00 }
]
}
""";
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
AllowTrailingCommas = true
};
OrderSummary? order = JsonSerializer.Deserialize<OrderSummary>(rawJson, options);
if (order != null)
{
Console.WriteLine($"Parsed Order {order.OrderId} with {order.LineItems.Count} items. Total: {order.TotalAmount:C}");
}
}
}
With Nullable Reference Types (#nullable enable), reference types like string are non-nullable by default. Marking a property with ? (string?, double?, bool?) explicitly declares to both the Roslyn compiler and static analyzers that null is an expected valid state:
#nullable enable
public class AccountSettings
{
// Non-nullable: Expects a valid string; compiler warns if initialized as null
public string DisplayName { get; set; } = string.Empty;
// Nullable reference type: Represents optional string
public string? BackupEmail { get; set; }
// Nullable value type (Nullable<bool>): Differentiates explicit false from null/missing
public bool? TwoFactorAuthRequired { get; set; }
}
System.Text.Json is substantially faster (typically 2x to 5x higher throughput) and allocates significantly less heap memory than Newtonsoft.Json. It operates directly on UTF-8 byte buffers via Utf8JsonReader and Utf8JsonWriter without decoding bytes to intermediate UTF-16 strings. In modern .NET 8 and 9, source generators ([JsonSerializable]) eliminate reflection entirely for near-instant AOT startup.
record instead of class for JSON DTO models?Use record (or record class) when modeling immutable data transfer objects (DTOs), webhook events, or external API responses where values should not change after deserialization. Records provide concise syntax, value-based equality checking (== compares property values rather than memory addresses), and built-in non-destructive mutation via with expressions.
According to official Microsoft .NET Framework Design Guidelines, all public properties and class names must be formatted in PascalCase. The [JsonPropertyName("snake_case_key")] attribute or the JsonNamingPolicy.CamelCase / JsonNamingPolicy.SnakeCaseLower configuration option bridges the gap, allowing .NET code to stay idiomatic without compromising interoperability with external JSON specifications.
Instead of manually typing class headers, PascalCase properties, and attribute tags, paste your JSON into our JSON to C# Class Converter to instantly generate modular C# classes or records with full serializer and nullable support.
Free, browser-based utilities to test, generate, and inspect C# Classes, Records & JSON Serialization in .NET payloads directly.
Convert JSON to C# classes with System.Text.Json or Newtonsoft serialization.
Convert JSON to TypeScript interfaces or type aliases instantly.
Convert JSON into idiomatic Rust structs with Serde Serialize and Deserialize derive macros.
Convert JSON to Go structs with json tags and idiomatic naming.
Convert JSON to Zod schema definitions with automatic TypeScript type inference.
Repair and fix malformed JSON data from AI outputs, API responses, and copy-paste.
Convert cURL commands to idiomatic code across 14 programming languages instantly.