DevToolBoxKOSTENLOS
Blog

JSON zu C# Klasse: Vollständiger Leitfaden mit System.Text.Json und Json.NET

12 Min. Lesezeitvon DevToolBox

TL;DR

Paste any JSON into the tool and instantly get strongly-typed C# classes with correct property names, nullable annotations, and support for System.Text.Json or Newtonsoft.Json. No installation required. Try our free JSON to C# tool →

Key Takeaways

  • Use System.Text.Json (built-in to .NET 6+) for new projects; use Newtonsoft.Json for legacy compatibility.
  • Prefer C# 9+ record types for immutable data transfer objects.
  • Enable #nullable enable to catch null-reference bugs at compile time.
  • Use [JsonPropertyName] to map snake_case JSON to PascalCase C# properties.
  • For arrays, generate List<T> or T[] depending on whether you need mutability.
  • Validate deserialized data with DataAnnotations or FluentValidation in ASP.NET Core.

Working with JSON APIs in C# means converting raw JSON into strongly-typed classes so the compiler and IDE can catch bugs before they reach production. This guide covers every aspect of JSON-to-C# conversion: from basic POCOs and nullable reference types through record types, enums, custom converters, inheritance, and ASP.NET Core integration.

Why Generate C# Classes from JSON

When you consume a REST API or read a JSON file in C#, you have two choices: work with dynamic types like JObject orJsonElement, or deserialize into strongly-typed classes. Strongly-typed classes win on every dimension that matters in production code:

  • Compile-time safety — the C# compiler rejects typos in property names and wrong types.
  • IntelliSense and refactoring — Visual Studio, Rider, and VS Code can autocomplete, rename, and navigate.
  • Null-reference prevention — with nullable reference types enabled, the compiler warns about unhandled nulls.
  • PerformanceJsonSerializer.Deserialize<T>() is faster than navigating a dynamic object graph at runtime.
  • Testability — you can create typed instances in unit tests without string parsing.
  • .NET 6+ source generators — System.Text.Json can generate serialization code at compile time for zero-reflection, AOT-compatible performance.

Generating classes manually from a large JSON response is error-prone and tedious. The JSON to C# tool handles nested objects, arrays, optional fields, and naming conventions automatically.

C# Class Structure from JSON: POCOs

A POCO (Plain Old CLR Object) is a class with public properties that match the JSON structure. Given this JSON:

{
  "user_id": 42,
  "full_name": "Alice Smith",
  "email": "alice@example.com",
  "is_active": true,
  "created_at": "2024-01-15T08:30:00Z"
}

The corresponding POCO with System.Text.Json attributes:

#nullable enable
using System;
using System.Text.Json.Serialization;

public class User
{
    [JsonPropertyName("user_id")]
    public int UserId { get; set; }

    [JsonPropertyName("full_name")]
    public string FullName { get; set; } = string.Empty;

    [JsonPropertyName("email")]
    public string Email { get; set; } = string.Empty;

    [JsonPropertyName("is_active")]
    public bool IsActive { get; set; }

    [JsonPropertyName("created_at")]
    public DateTimeOffset CreatedAt { get; set; }
}

The [JsonPropertyName] attribute maps the snake_case JSON key to the PascalCase C# property. The string.Empty default prevents nullable warnings for required string properties.

System.Text.Json (.NET Core 3+)

System.Text.Json is Microsoft's built-in JSON library, available from .NET Core 3.0 onward and included by default in ASP.NET Core. It prioritizes performance and correctness over convenience.

Deserializing JSON

using System.Text.Json;

string json = await httpClient.GetStringAsync("https://api.example.com/users/42");
User? user = JsonSerializer.Deserialize<User>(json);

// Or directly from HttpClient (System.Net.Http.Json):
User? user2 = await httpClient.GetFromJsonAsync<User>("https://api.example.com/users/42");

Serializing to JSON

var user = new User
{
    UserId = 42,
    FullName = "Alice Smith",
    Email = "alice@example.com",
    IsActive = true,
    CreatedAt = DateTimeOffset.UtcNow,
};

string json = JsonSerializer.Serialize(user);
// {"user_id":42,"full_name":"Alice Smith","email":"alice@example.com","is_active":true,"created_at":"2024-01-15T08:30:00+00:00"}

JsonSerializerOptions

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,       // camelCase output
    PropertyNameCaseInsensitive = true,                       // case-insensitive read
    WriteIndented = true,                                     // pretty print
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, // omit nulls
    Converters = { new JsonStringEnumConverter() },           // enums as strings
};

string json = JsonSerializer.Serialize(user, options);
User? result = JsonSerializer.Deserialize<User>(json, options);

Key Attributes

[JsonPropertyName("api_key")]     // map to specific JSON key name
[JsonIgnore]                       // never serialize/deserialize
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]  // omit if null
[JsonRequired]                     // throw if key missing (System.Text.Json in .NET 7+)
[JsonInclude]                      // include non-public members
[JsonConverter(typeof(MyConverter))] // custom converter

Newtonsoft.Json (Json.NET)

Json.NET by James Newton-King has been the dominant C# JSON library for over a decade. It remains popular for its rich feature set: LINQ to JSON, flexible converters, and support for older .NET Framework versions.

Deserializing with Newtonsoft.Json

using Newtonsoft.Json;

string json = File.ReadAllText("data.json");

// Deserialize to typed class:
User? user = JsonConvert.DeserializeObject<User>(json);

// Dynamic / partial parsing with JObject:
JObject obj = JObject.Parse(json);
string? name = obj["full_name"]?.Value<string>();
int userId = (int)obj["user_id"]!;

Newtonsoft.Json Attributes

using Newtonsoft.Json;

public class User
{
    [JsonProperty("user_id")]
    public int UserId { get; set; }

    [JsonProperty("full_name")]
    public string FullName { get; set; } = string.Empty;

    [JsonIgnore]
    public string InternalNote { get; set; } = string.Empty;

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string? OptionalField { get; set; }
}

JsonSerializerSettings

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    NullValueHandling = NullValueHandling.Ignore,
    DateTimeZoneHandling = DateTimeZoneHandling.Utc,
    Formatting = Formatting.Indented,
    Converters = { new StringEnumConverter() },
};

string json = JsonConvert.SerializeObject(user, settings);

LINQ to JSON

// Build JSON dynamically without a typed class:
var jObject = new JObject
{
    ["name"] = "Alice",
    ["scores"] = new JArray(95, 87, 92),
    ["meta"] = new JObject { ["active"] = true },
};

// Query deeply nested JSON without deserializing:
JArray? items = JArray.Parse(json);
var names = items.Select(x => x["name"]?.ToString()).ToList();

Record Types (C# 9+)

C# 9 introduced record types: reference types with value-based equality, a concise positional syntax, and init-only setters. They are ideal for immutable DTOs that represent deserialized JSON payloads.

Positional Record

// Concise positional syntax — compiler generates constructor and Deconstruct:
public record UserRecord(
    [property: JsonPropertyName("user_id")] int UserId,
    [property: JsonPropertyName("full_name")] string FullName,
    [property: JsonPropertyName("email")] string Email
);

// Works with System.Text.Json:
var user = JsonSerializer.Deserialize<UserRecord>(json);
Console.WriteLine(user?.FullName);

Standard Record with Init Setters

public record UserRecord
{
    [JsonPropertyName("user_id")]
    public int UserId { get; init; }

    [JsonPropertyName("full_name")]
    public required string FullName { get; init; }   // required = C# 11

    [JsonPropertyName("email")]
    public required string Email { get; init; }
}

// Immutable — properties can only be set during construction:
var user = new UserRecord { UserId = 1, FullName = "Bob", Email = "bob@x.com" };

// Non-destructive mutation with 'with':
var updated = user with { Email = "bob@y.com" };

Value Records (record struct, C# 10+)

// Stack-allocated, value equality, no heap allocation for small types:
public readonly record struct Point(double X, double Y);

var p = new Point(1.5, 2.5);
var q = new Point(1.5, 2.5);
Console.WriteLine(p == q); // true — value equality

Nullable Reference Types and the required Keyword

Enabling nullable reference types (#nullable enable or project-wide via <Nullable>enable</Nullable> in .csproj) turns null-safety into a compiler feature.

#nullable enable

public class Product
{
    // Non-nullable — must always be present:
    public required string Name { get; init; }   // C# 11 required
    public decimal Price { get; set; }

    // Nullable — may be missing from JSON:
    public string? Description { get; set; }
    public string? ImageUrl { get; set; }

    // Nullable value type:
    public int? StockCount { get; set; }
}

The required keyword (C# 11, .NET 7+) enforces that a property is set during object initialization and that System.Text.Json throwsJsonException if the JSON key is missing (when using[JsonRequired] in conjunction).

MaybeNull and NotNull Attributes

using System.Diagnostics.CodeAnalysis;

public class Repository
{
    // Tells compiler this method might return null even though return type is string:
    [return: MaybeNull]
    public string GetCachedValue(string key) => cache.TryGetValue(key, out var v) ? v : null!;

    // Tells compiler: after this method returns, parameter is not null:
    public void EnsureNotNull([NotNull] string? value)
    {
        if (value is null) throw new ArgumentNullException(nameof(value));
    }
}

Nested Classes and Arrays

JSON objects nest naturally into C# nested classes, and JSON arrays becomeList<T>, T[], or IReadOnlyList<T> properties.

// JSON:
// {
//   "order_id": "ORD-001",
//   "customer": { "id": 5, "name": "Alice" },
//   "items": [
//     { "sku": "A1", "qty": 2, "price": 9.99 },
//     { "sku": "B2", "qty": 1, "price": 24.99 }
//   ],
//   "tags": ["urgent", "fragile"]
// }

public class Order
{
    [JsonPropertyName("order_id")]
    public string OrderId { get; set; } = string.Empty;

    [JsonPropertyName("customer")]
    public Customer Customer { get; set; } = new();

    [JsonPropertyName("items")]
    public List<OrderItem> Items { get; set; } = new();

    [JsonPropertyName("tags")]
    public IReadOnlyList<string> Tags { get; set; } = Array.Empty<string>();
}

public class Customer
{
    [JsonPropertyName("id")]
    public int Id { get; set; }

    [JsonPropertyName("name")]
    public string Name { get; set; } = string.Empty;
}

public class OrderItem
{
    [JsonPropertyName("sku")]
    public string Sku { get; set; } = string.Empty;

    [JsonPropertyName("qty")]
    public int Qty { get; set; }

    [JsonPropertyName("price")]
    public decimal Price { get; set; }
}

Dictionary for Dynamic Keys

// JSON: { "scores": { "alice": 95, "bob": 87, "carol": 91 } }
public class ScoreBoard
{
    [JsonPropertyName("scores")]
    public Dictionary<string, int> Scores { get; set; } = new();
}

// Nested dictionary:
// { "matrix": { "row1": { "a": 1, "b": 2 } } }
public Dictionary<string, Dictionary<string, int>> Matrix { get; set; } = new();

Enums with JSON

By default, System.Text.Json serializes enums as integers. To serialize as strings (which is far more readable and stable in APIs), use JsonStringEnumConverter.

using System.Text.Json.Serialization;

public enum OrderStatus
{
    Pending,
    Processing,
    Shipped,
    Delivered,
    Cancelled,
}

public class Order
{
    [JsonPropertyName("status")]
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public OrderStatus Status { get; set; }
}

// Serialize: { "status": "Shipped" }
// Deserialize: "Shipped" -> OrderStatus.Shipped

Global Enum Converter (System.Text.Json)

var options = new JsonSerializerOptions
{
    Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) },
};
// All enums serialized as camelCase strings: "shipped" instead of "Shipped"

Enum with JsonEnumMemberName (.NET 9+)

// .NET 9 adds [JsonStringEnumMemberName] for custom string values:
[JsonConverter(typeof(JsonStringEnumConverter<Priority>))]
public enum Priority
{
    [JsonStringEnumMemberName("low")]    Low,
    [JsonStringEnumMemberName("med")]    Medium,
    [JsonStringEnumMemberName("high")]   High,
}
// JSON: "priority": "med"  <->  Priority.Medium

Custom Enum Converter for Unknown Values

public class SafeEnumConverter<T> : JsonConverter<T> where T : struct, Enum
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        string? value = reader.GetString();
        return Enum.TryParse<T>(value, ignoreCase: true, out var result)
            ? result
            : default;   // fall back to 0 (first enum value) for unknown strings
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
        => writer.WriteStringValue(value.ToString());
}

Date and Time Handling

DateTime vs DateTimeOffset vs DateOnly

  • DateTime — local or UTC, no offset stored. Avoid for APIs; can cause timezone bugs.
  • DateTimeOffset — stores offset from UTC. Prefer this for timestamps in APIs.
  • DateOnly (.NET 6+) — date without time. Ideal for birthdays, due dates, etc.
  • TimeOnly (.NET 6+) — time without date. Ideal for opening hours, schedules.
public class Event
{
    [JsonPropertyName("start_time")]
    public DateTimeOffset StartTime { get; set; }    // "2024-03-15T09:00:00+00:00"

    [JsonPropertyName("date")]
    public DateOnly Date { get; set; }               // "2024-03-15"

    [JsonPropertyName("open_at")]
    public TimeOnly OpenAt { get; set; }             // "09:00:00"
}

Unix Timestamp Custom Converter

public class UnixTimestampConverter : JsonConverter<DateTimeOffset>
{
    public override DateTimeOffset Read(ref Utf8JsonReader reader,
        Type typeToConvert, JsonSerializerOptions options)
        => DateTimeOffset.FromUnixTimeSeconds(reader.GetInt64());

    public override void Write(Utf8JsonWriter writer,
        DateTimeOffset value, JsonSerializerOptions options)
        => writer.WriteNumberValue(value.ToUnixTimeSeconds());
}

// Usage:
public class LoginEvent
{
    [JsonPropertyName("timestamp")]
    [JsonConverter(typeof(UnixTimestampConverter))]
    public DateTimeOffset Timestamp { get; set; }
}
// JSON: { "timestamp": 1710489600 }  -> DateTimeOffset(2024-03-15T08:00:00Z)

Custom Converters

When built-in deserialization does not handle a particular JSON format — such as a type that serializes differently depending on a discriminator field, a polymorphic number that can also be a string, or a compact binary format — implementJsonConverter<T>.

// A converter that accepts both string and number for a "version" field:
// JSON: { "version": "3.1" } or { "version": 3 }
public class FlexibleVersionConverter : JsonConverter<Version>
{
    public override Version? Read(ref Utf8JsonReader reader,
        Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.String)
        {
            return Version.TryParse(reader.GetString(), out var v) ? v : null;
        }
        if (reader.TokenType == JsonTokenType.Number)
        {
            return new Version(reader.GetInt32(), 0);
        }
        throw new JsonException($"Unexpected token: {reader.TokenType}");
    }

    public override void Write(Utf8JsonWriter writer,
        Version value, JsonSerializerOptions options)
        => writer.WriteStringValue(value.ToString());
}

// Register globally:
var options = new JsonSerializerOptions
{
    Converters = { new FlexibleVersionConverter() },
};

JsonConverterFactory for Generic Types

// A factory that creates converters for any Wrapper<T>:
public class WrapperConverterFactory : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert)
        => typeToConvert.IsGenericType
           && typeToConvert.GetGenericTypeDefinition() == typeof(Wrapper<>);

    public override JsonConverter? CreateConverter(Type typeToConvert,
        JsonSerializerOptions options)
    {
        Type itemType = typeToConvert.GetGenericArguments()[0];
        return (JsonConverter?)Activator.CreateInstance(
            typeof(WrapperConverter<>).MakeGenericType(itemType));
    }
}

Inheritance and Polymorphism

.NET 7+ System.Text.Json supports polymorphic serialization with[JsonPolymorphic] and [JsonDerivedType] attributes, replacing the manual discriminator patterns needed in earlier versions.

using System.Text.Json.Serialization;

[JsonPolymorphic(TypeDiscriminatorPropertyName = "$type")]
[JsonDerivedType(typeof(CircleShape), typeDiscriminator: "circle")]
[JsonDerivedType(typeof(RectangleShape), typeDiscriminator: "rectangle")]
public abstract class Shape
{
    public string Color { get; set; } = "black";
}

public class CircleShape : Shape
{
    public double Radius { get; set; }
}

public class RectangleShape : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
}

// Serialize:
Shape shape = new CircleShape { Color = "red", Radius = 5.0 };
string json = JsonSerializer.Serialize<Shape>(shape);
// { "$type": "circle", "radius": 5.0, "color": "red" }

// Deserialize back to the correct subtype:
Shape? result = JsonSerializer.Deserialize<Shape>(json);
// result is CircleShape

Manual Discriminator (older .NET / Newtonsoft.Json)

// With Newtonsoft.Json: use JsonSubTypes NuGet package
// or a custom converter that reads a discriminator field first:

public class ShapeConverter : JsonConverter
{
    public override object? ReadJson(JsonReader reader, Type objectType,
        object? existingValue, JsonSerializer serializer)
    {
        var obj = JObject.Load(reader);
        string? type = obj["$type"]?.Value<string>();
        return type switch
        {
            "circle"    => obj.ToObject<CircleShape>(serializer),
            "rectangle" => obj.ToObject<RectangleShape>(serializer),
            _           => throw new JsonException($"Unknown type: {type}"),
        };
    }

    public override bool CanConvert(Type objectType) => objectType == typeof(Shape);
    public override void WriteJson(JsonWriter w, object? v, JsonSerializer s)
        => throw new NotSupportedException();
}

Validation with DataAnnotations

After deserializing JSON into a C# class, validate the data before acting on it. The System.ComponentModel.DataAnnotations namespace provides attributes recognized by ASP.NET Core model binding and theValidator class.

using System.ComponentModel.DataAnnotations;

public class CreateUserRequest
{
    [Required]
    [StringLength(50, MinimumLength = 2)]
    [JsonPropertyName("username")]
    public string Username { get; set; } = string.Empty;

    [Required]
    [EmailAddress]
    [JsonPropertyName("email")]
    public string Email { get; set; } = string.Empty;

    [Required]
    [Range(13, 120, ErrorMessage = "Age must be between 13 and 120.")]
    [JsonPropertyName("age")]
    public int Age { get; set; }

    [Url]
    [JsonPropertyName("website")]
    public string? Website { get; set; }

    [RegularExpression(@"^+?[1-9]d{7,14}$")]
    [JsonPropertyName("phone")]
    public string? Phone { get; set; }
}

// Manual validation outside ASP.NET Core:
var request = JsonSerializer.Deserialize<CreateUserRequest>(json)!;
var context = new ValidationContext(request);
var results = new List<ValidationResult>();
bool valid = Validator.TryValidateObject(request, context, results, validateAllProperties: true);

if (!valid)
{
    foreach (var error in results)
        Console.WriteLine(error.ErrorMessage);
}

FluentValidation (Recommended for Complex Rules)

// Install: dotnet add package FluentValidation
using FluentValidation;

public class CreateUserRequestValidator : AbstractValidator<CreateUserRequest>
{
    public CreateUserRequestValidator()
    {
        RuleFor(x => x.Username)
            .NotEmpty()
            .Length(2, 50)
            .Matches(@"^[a-zA-Z0-9_]+$").WithMessage("Username can only contain letters, digits and underscores.");

        RuleFor(x => x.Email)
            .NotEmpty()
            .EmailAddress();

        RuleFor(x => x.Age)
            .InclusiveBetween(13, 120);
    }
}

ASP.NET Core Integration

ASP.NET Core uses System.Text.Json by default for model binding and API responses. Your C# classes generated from JSON work directly as controller parameters and return types.

Controller Actions

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    // POST body is automatically deserialized from JSON:
    [HttpPost]
    public IActionResult CreateUser([FromBody] CreateUserRequest request)
    {
        if (!ModelState.IsValid)
            return ValidationProblem(ModelState);

        // process...
        return CreatedAtAction(nameof(GetUser), new { id = 1 }, new { id = 1 });
    }

    // Return type is automatically serialized to JSON:
    [HttpGet("{id:int}")]
    public ActionResult<User> GetUser(int id)
    {
        var user = new User { UserId = id, FullName = "Alice", Email = "alice@x.com" };
        return Ok(user);
    }
}

HttpClient with GetFromJsonAsync

// dotnet add package Microsoft.Extensions.Http
// Available via IHttpClientFactory in DI:
public class UserService
{
    private readonly HttpClient _http;

    public UserService(HttpClient http) => _http = http;

    public async Task<User?> GetUserAsync(int id)
    {
        // Deserializes response JSON automatically:
        return await _http.GetFromJsonAsync<User>($"/api/users/{id}");
    }

    public async Task CreateUserAsync(CreateUserRequest req)
    {
        // Serializes req to JSON and sends as POST body:
        var response = await _http.PostAsJsonAsync("/api/users", req);
        response.EnsureSuccessStatusCode();
    }
}

Global JSON Options in Program.cs

// Program.cs (.NET 6+ minimal API):
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
});

// Or with AddControllers():
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    });

Minimal API with JSON

// Minimal API — model binding and JSON serialization built in:
app.MapPost("/api/users", async (CreateUserRequest req, IValidator<CreateUserRequest> validator) =>
{
    var result = await validator.ValidateAsync(req);
    if (!result.IsValid)
        return Results.ValidationProblem(result.ToDictionary());

    return Results.Created("/api/users/1", new User { UserId = 1, FullName = req.Username });
});

app.MapGet("/api/users/{id:int}", (int id) =>
    Results.Ok(new User { UserId = id, FullName = "Alice", Email = "alice@x.com" }));

Tools for JSON-to-C# Class Generation

ToolTypeBest For
DevToolBox JSON to C#Online free toolQuick POCO/record generation, no install
Visual Studio "Paste JSON as Classes"IDE built-inCopy JSON from clipboard directly in VS
quicktype (quicktype.io)Online / CLI / pluginsMulti-language generation including C#
NSwagCLI / NuGetGenerate C# clients from OpenAPI/Swagger specs
NJsonSchemaNuGet libraryGenerate C# classes from JSON Schema
Newtonsoft.Json SchemaNuGet libraryJSON Schema validation with Json.NET
ReSharper / RiderIDE pluginPaste JSON as classes with advanced type inference

Visual Studio: Paste JSON as Classes

In Visual Studio 2019+, copy JSON to clipboard, then go to Edit → Paste Special → Paste JSON as Classes. The IDE generates a complete class hierarchy using Newtonsoft.Json attributes. Limitations: it does not support nullable reference types or record types. Use the DevToolBox JSON to C# tool for modern output with System.Text.Json, records, and nullable annotations.

Source Generators (.NET 6+ AOT)

// Enable System.Text.Json source generation for AOT / trimming compatibility:
using System.Text.Json.Serialization;

[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(List<User>))]
[JsonSerializable(typeof(CreateUserRequest))]
public partial class AppJsonContext : JsonSerializerContext { }

// Use context instead of default options:
string json = JsonSerializer.Serialize(user, AppJsonContext.Default.User);
User? result = JsonSerializer.Deserialize(json, AppJsonContext.Default.User);

// In minimal APIs:
app.MapGet("/user", () => new User { UserId = 1, FullName = "Alice" })
   .WithMetadata(AppJsonContext.Default.User);

Frequently Asked Questions

What is the difference between System.Text.Json and Newtonsoft.Json?

System.Text.Json is built into .NET Core 3.0+ and .NET 5+, offering better performance and lower allocations. Newtonsoft.Json (Json.NET) is a third-party library with richer features like LINQ to JSON, more flexible converters, and broader legacy support. For new projects on .NET 6+ use System.Text.Json; add Newtonsoft.Json only when you need features it lacks or must integrate with existing code.

How do I deserialize JSON with snake_case keys into PascalCase C# properties?

With System.Text.Json, set JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower (available from .NET 8) or use [JsonPropertyName("snake_case_key")] on each property. With Newtonsoft.Json, set ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() } or use [JsonProperty("snake_case_key")] attributes.

Should I use C# records or classes for deserialized JSON?

Records (C# 9+) are ideal for immutable DTOs: they support positional constructors, init-only setters, and built-in value equality. Use records when data should not change after deserialization. Use classes when you need mutable state, inheritance hierarchies, or complex initialization logic. Both work with System.Text.Json and Newtonsoft.Json.

How do I handle nullable JSON fields in C#?

Enable nullable reference types with #nullable enable (or project-wide in .csproj). Mark optional JSON fields as nullable: string? for reference types and int? for value types. System.Text.Json respects nullable annotations and will set null for missing JSON keys. Use [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] to omit null properties from serialized output.

How do I deserialize JSON arrays into C# collections?

System.Text.Json automatically deserializes JSON arrays into List<T>, T[], IEnumerable<T>, IList<T>, and IReadOnlyList<T>. Use List<T> for mutable collections and IReadOnlyList<T> or T[] for read-only data. For dictionaries, use Dictionary<string, T> which maps to JSON objects with dynamic keys. Nested arrays deserialize into List<List<T>> or T[][].

How do I serialize and deserialize C# enums as strings?

With System.Text.Json, add JsonStringEnumConverter to the converters list in JsonSerializerOptions, or use [JsonConverter(typeof(JsonStringEnumConverter))] on the enum property. This converts enum values to their string names. With Newtonsoft.Json, add StringEnumConverter to JsonSerializerSettings.Converters or use [JsonConverter(typeof(StringEnumConverter))] on the property.

How do I handle date and time values in JSON with C#?

System.Text.Json handles DateTime and DateTimeOffset as ISO 8601 strings by default. .NET 6 adds DateOnly and TimeOnly types which also serialize to ISO 8601. For Newtonsoft.Json, use IsoDateTimeConverter (default) or configure DateFormatString. To handle Unix timestamps, implement a custom JsonConverter<DateTimeOffset> that reads a long value and converts it with DateTimeOffset.FromUnixTimeSeconds().

How do I use the JSON to C# tool to generate classes for ASP.NET Core?

Paste your JSON into the tool, select System.Text.Json or Newtonsoft.Json mode, then copy the generated classes into your ASP.NET Core project. For model binding, place the class in a Models folder and reference it as the controller action parameter. For HttpClient deserialization, use GetFromJsonAsync<MyClass>() from the System.Net.Http.Json package. Add DataAnnotations attributes like [Required] and [Range] for automatic model validation.

Generate C# Classes from JSON Instantly

Paste your JSON and get ready-to-use C# classes with nullable types, System.Text.Json attributes, and record support.

Open JSON to C# Tool →
𝕏 Twitterin LinkedIn
War das hilfreich?

Bleiben Sie informiert

Wöchentliche Dev-Tipps und neue Tools.

Kein Spam. Jederzeit abbestellbar.

Verwandte Tools ausprobieren

C#JSON to C#{ }JSON FormatterTSJSON to TypeScriptJVJSON to Java Class

Verwandte Artikel

JSON zu TypeScript Online: Der komplette Entwickler-Guide

Lernen Sie, TypeScript-Typen automatisch aus JSON zu generieren. Interface vs Type, optionale/nullable Felder, verschachtelte Objekte, Union-Typen, Zod-Laufzeitvalidierung, generische API-Response-Typen und tsconfig Best Practices.

JSON zu Java Klasse: Vollständiger POJO-Generierungsleitfaden mit Jackson

Lernen Sie, wie Sie JSON mit Jackson, Lombok und Gson in Java-Klassen, POJOs und Records konvertieren.