DevToolBoxFREE
BlogAdvertise

JSON zu C#-Klasse: System.Text.Json, Newtonsoft & Records Anleitung

17 Min. Lesezeitvon DevToolBox

Die Konvertierung von JSON in C#-Klassen ist eine wesentliche Aufgabe in der modernen .NET-Entwicklung. Ob Sie eine ASP.NET Core Web-API, ein Unity-Spiel, eine Blazor-App oder einen MAUI-Client erstellen, Sie benotigen stark typisierte C#-Klassen zur Deserialisierung von JSON-Antworten. Dieser Leitfaden behandelt Typ-Mapping, System.Text.Json, Newtonsoft.Json, Records, POCO-Generierung und Best Practices.

Testen Sie unseren kostenlosen Online JSON-zu-C#-Konverter.

Was ist JSON-zu-C#-Klassenkonvertierung?

JSON ist das universelle Datenaustauschformat fur Web-APIs und Cloud-Dienste. C# als statisch typisierte Sprache erfordert explizite Klassendefinitionen. Die JSON-zu-C#-Konvertierung analysiert ein JSON-Dokument und erzeugt entsprechende C#-Klassen mit typisierten Eigenschaften und Serialisierungsattributen.

In einer typischen ASP.NET Core-Anwendung empfangt ein Controller den HTTP-Request-Body als JSON-String. Das Framework muss dieses JSON mit System.Text.Json oder Newtonsoft.Json in C#-Objekte konvertieren. Ein JSON-zu-C#-Konverter automatisiert die Erstellung dieser Datenobjekte.

Die gleiche Konvertierung ist in Unity, Blazor und Azure Functions wesentlich. Der Prozess ist identisch: JSON-Struktur inspizieren, Typen bestimmen, Verschachtelung und Arrays behandeln.

JSON zu C#: Typ-Mapping

Das Verstandnis der Zuordnung von JSON-Typen zu C#-Typen ist die Grundlage jeder Konvertierung:

JSON-TypBeispielC#-Typ(en)Hinweise
string"hello"stringImmer System.String
number (ganzzahlig)42int, longint? wenn nullable
number (dezimal)3.14double, decimaldecimal fur Finanzdaten
booleantrueboolbool? wenn nullable
nullnullnullNullable-Typen
array[1,2]List<T>List bevorzugt
object{"k":"v"}Verschachtelte KlasseStark typisierte Klassen bevorzugt

Bei der Generierung von C#-Klassen aus JSON ist die Wahl zwischen Werttypen und Nullable-Typen wichtig. Fur Geldwerte immer decimal verwenden.

Wie die JSON-zu-C#-Konvertierung funktioniert

Ein JSON-zu-C#-Konverter folgt einem systematischen Prozess:

  1. JSON-Struktur parsen: Aufbau eines Syntaxbaums.
  2. Eigenschaftstypen ableiten: C#-Typ fur jede Eigenschaft bestimmen.
  3. Namen generieren: Konvertierung in PascalCase.
  4. Verschachtelte Objekte behandeln: Jedes verschachtelte Objekt erzeugt eine separate Klasse.
  5. Arrays behandeln: Elementtyp-Analyse.
  6. Attribute hinzufugen: [JsonPropertyName] oder [JsonProperty].
  7. Quellcode ausgeben: Formatierter C#-Code.

Codebeispiele: JSON zu C# mit System.Text.Json und Newtonsoft

System.Text.Json (.NET 8+): JsonSerializer und Attribute

System.Text.Json ist der integrierte Hochleistungs-JSON-Serialisierer in .NET. Ab .NET 8 mit Quellgeneratoren fur AOT-Kompilierung:

// === Sample JSON ===
// {
//   "user_id": 1001,
//   "user_name": "Alice",
//   "email": "alice@example.com",
//   "is_active": true,
//   "balance": 1250.75,
//   "tags": ["admin", "developer"],
//   "address": {
//     "street": "123 Main St",
//     "city": "Springfield",
//     "zip_code": "62704"
//   }
// }

// === C# class with System.Text.Json attributes ===
using System.Text.Json;
using System.Text.Json.Serialization;

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

    [JsonPropertyName("user_name")]
    public string UserName { get; set; } = "";

    public string Email { get; set; } = "";

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

    public decimal Balance { get; set; }

    public List<string> Tags { get; set; } = new();

    public Address Address { get; set; } = new();
}

public class Address
{
    public string Street { get; set; } = "";
    public string City { get; set; } = "";

    [JsonPropertyName("zip_code")]
    public string ZipCode { get; set; } = "";
}

// === Deserialization with JsonSerializer ===
var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

// Single object
User? user = JsonSerializer.Deserialize<User>(jsonString, options);

// List of objects
List<User>? users = JsonSerializer.Deserialize<List<User>>(
    jsonArrayString, options);

// === Custom JsonConverter for special cases ===
public class EpochToDateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(
        ref Utf8JsonReader reader, Type typeToConvert,
        JsonSerializerOptions options)
    {
        return DateTimeOffset.FromUnixTimeSeconds(
            reader.GetInt64()).DateTime;
    }

    public override void Write(
        Utf8JsonWriter writer, DateTime value,
        JsonSerializerOptions options)
    {
        writer.WriteNumberValue(
            new DateTimeOffset(value).ToUnixTimeSeconds());
    }
}

// Usage: [JsonConverter(typeof(EpochToDateTimeConverter))]
// public DateTime CreatedAt { get; set; }

// === .NET 8 Source Generator (AOT-friendly) ===
[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(List<User>))]
public partial class AppJsonContext : JsonSerializerContext { }

// Zero-reflection deserialization:
User? u = JsonSerializer.Deserialize(
    jsonString, AppJsonContext.Default.User);

Newtonsoft.Json: JsonConvert und Attribute

Newtonsoft.Json ist der De-facto-Standard fur C# JSON-Deserialisierung mit JObject, LINQ-to-JSON und benutzerdefinierten JsonConverter:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;

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

    [JsonProperty("user_name")]
    public string UserName { get; set; } = "";

    public string Email { get; set; } = "";

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

    public decimal Balance { get; set; }

    public List<string> Tags { get; set; } = new();

    public Address Address { get; set; } = new();
}

// === Deserialization with JsonConvert ===
var settings = new JsonSerializerSettings
{
    MissingMemberHandling = MissingMemberHandling.Ignore,
    NullValueHandling = NullValueHandling.Ignore,
    DateFormatString = "yyyy-MM-ddTHH:mm:ssZ"
};

// Single object
User? user = JsonConvert.DeserializeObject<User>(
    jsonString, settings);

// List of objects
List<User>? users = JsonConvert.DeserializeObject<List<User>>(
    jsonArrayString, settings);

// === Dynamic parsing with JObject ===
JObject obj = JObject.Parse(jsonString);
string? name = (string?)obj["user_name"];
JArray? tags = (JArray?)obj["tags"];
int tagCount = tags?.Count ?? 0;

// LINQ-to-JSON queries
var activeUsers = JArray.Parse(jsonArrayString)
    .Where(u => (bool)u["is_active"]!)
    .Select(u => (string?)u["user_name"])
    .ToList();

// === Custom JsonConverter ===
public class BoolToIntConverter : JsonConverter<bool>
{
    public override bool ReadJson(
        JsonReader reader, Type objectType, bool existingValue,
        bool hasExistingValue, JsonSerializer serializer)
    {
        return Convert.ToInt32(reader.Value) == 1;
    }

    public override void WriteJson(
        JsonWriter writer, bool value,
        JsonSerializer serializer)
    {
        writer.WriteValue(value ? 1 : 0);
    }
}

// Usage: [JsonConverter(typeof(BoolToIntConverter))]
// public bool IsActive { get; set; }

C# Records: Unveranderliche Datenmodelle

C# 9+ Records bieten eine kompakte Art, unveranderliche Datenmodelle zu definieren mit Equals, GetHashCode und with-Ausdrucken:

// C# Record classes for JSON deserialization (C# 9+)
using System.Text.Json.Serialization;

public record User(
    [property: JsonPropertyName("user_id")] long UserId,
    [property: JsonPropertyName("user_name")] string UserName,
    string Email,
    [property: JsonPropertyName("is_active")] bool IsActive,
    decimal Balance,
    List<string> Tags,
    Address Address
);

public record Address(
    string Street,
    string City,
    [property: JsonPropertyName("zip_code")] string ZipCode
);

// Deserialization works seamlessly with records
var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};
User? user = JsonSerializer.Deserialize<User>(json, options);

// Records are immutable: use "with" for modified copies
User updated = user! with { Email = "new@example.com" };

// Init-only record class (C# 10+)
public record class Product
{
    public required long Id { get; init; }
    public required string Name { get; init; }
    public required decimal Price { get; init; }
    public bool InStock { get; init; }
    public List<string> Categories { get; init; } = new();
}

// Value-based equality: two records with same data are equal
var p1 = new Product { Id = 1, Name = "Keyboard", Price = 79.99m };
var p2 = new Product { Id = 1, Name = "Keyboard", Price = 79.99m };
Console.WriteLine(p1 == p2);  // True

Manuelles POCO: Klasse mit Eigenschaften

Fur volle Kontrolle bietet ein traditionelles POCO mit INotifyPropertyChanged oder AutoMapper maximale Flexibilitat:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text.Json.Serialization;

// POCO with INotifyPropertyChanged for WPF/MAUI data binding
public class Product : INotifyPropertyChanged
{
    private long _id;
    private string _name = "";
    private decimal _price;
    private bool _inStock;
    private List<string> _categories = new();

    [JsonPropertyName("product_id")]
    public long Id
    {
        get => _id;
        set => SetField(ref _id, value);
    }

    public string Name
    {
        get => _name;
        set => SetField(ref _name, value);
    }

    public decimal Price
    {
        get => _price;
        set => SetField(ref _price, value);
    }

    [JsonPropertyName("in_stock")]
    public bool InStock
    {
        get => _inStock;
        set => SetField(ref _inStock, value);
    }

    public List<string> Categories
    {
        get => _categories;
        set => SetField(ref _categories, value);
    }

    // INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler? PropertyChanged;

    private void OnPropertyChanged(
        [CallerMemberName] string? name = null)
    {
        PropertyChanged?.Invoke(
            this, new PropertyChangedEventArgs(name));
    }

    private bool SetField<T>(
        ref T field, T value,
        [CallerMemberName] string? name = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
            return false;
        field = value;
        OnPropertyChanged(name);
        return true;
    }

    // Override ToString for debugging
    public override string ToString()
        => $"Product {{ Id={Id}, Name={Name}, Price={Price} }}";
}

// Usage with AutoMapper (DTO to domain model):
// var config = new MapperConfiguration(cfg =>
//     cfg.CreateMap<ProductDto, Product>());
// var mapper = config.CreateMapper();
// Product product = mapper.Map<Product>(dto);

Arbeiten mit verschachtelten JSON-Strukturen

Reale APIs enthalten tief verschachtelte Objekte und polymorphe Typen:

Verschachtelte Objekte: Jede Verschachtelungsebene erzeugt eine separate C#-Klasse.

Objekt-Arrays: "items": [{"id": 1}] wird zu List<Item>.

Polymorphe Deserialisierung: .NET 7+ unterstutzt [JsonDerivedType] und [JsonPolymorphic].

// Polymorphic deserialization with .NET 7+ System.Text.Json
using System.Text.Json.Serialization;

[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")]
[JsonDerivedType(typeof(EmailNotification), "email")]
[JsonDerivedType(typeof(SmsNotification), "sms")]
[JsonDerivedType(typeof(PushNotification), "push")]
public abstract class Notification
{
    public string Type { get; set; } = "";
    public string Message { get; set; } = "";
    public DateTime CreatedAt { get; set; }
}

public class EmailNotification : Notification
{
    public string Recipient { get; set; } = "";
    public string Subject { get; set; } = "";
}

public class SmsNotification : Notification
{
    public string PhoneNumber { get; set; } = "";
}

public class PushNotification : Notification
{
    public string DeviceToken { get; set; } = "";
    public string Title { get; set; } = "";
}

// JSON input:
// {"type":"email","message":"Hello","recipient":"a@b.com","subject":"Hi"}
// Automatically deserializes to EmailNotification

// Nested classes with arrays example
public class ApiResponse
{
    public bool Success { get; set; }
    public UserData Data { get; set; } = new();
    public List<ErrorDetail> Errors { get; set; } = new();
}

public class UserData
{
    public User User { get; set; } = new();
    public List<Order> Orders { get; set; } = new();
    public Address BillingAddress { get; set; } = new();
    public Address ShippingAddress { get; set; } = new();
}

public class Order
{
    public long OrderId { get; set; }
    public decimal Total { get; set; }
    public List<OrderItem> Items { get; set; } = new();
}

public class OrderItem
{
    public long ProductId { get; set; }
    public string Name { get; set; } = "";
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
}

Fortgeschrittene Muster: Quellgeneratoren, AOT und Nullable-Typen

.NET 8 Quellgeneratoren fur System.Text.Json erzeugen Serialisierungscode zur Kompilierzeit und ermoglichen Native-AOT-Bereitstellung:

// .NET 8 Source Generator for AOT-friendly serialization
using System.Text.Json;
using System.Text.Json.Serialization;

public record Product(
    [property: JsonPropertyName("product_id")] long ProductId,
    string Name,
    decimal Price,
    [property: JsonPropertyName("in_stock")] bool InStock,
    List<string> Tags,
    [property: JsonPropertyName("created_at")] DateTime CreatedAt
);

// Source generator context
[JsonSerializable(typeof(Product))]
[JsonSerializable(typeof(List<Product>))]
[JsonSourceGenerationOptions(
    PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    GenerationMode = JsonSourceGenerationMode.Default)]
public partial class AppJsonContext : JsonSerializerContext { }

// Zero-reflection serialization (AOT-compatible)
var product = JsonSerializer.Deserialize(
    json, AppJsonContext.Default.Product);
var jsonOut = JsonSerializer.Serialize(
    product, AppJsonContext.Default.Product);

// Works with ASP.NET Core minimal APIs
var builder = WebApplication.CreateBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain
        .Insert(0, AppJsonContext.Default);
});

Nullable-Referenztypen in C# 8+ bieten Kompilierzeit-Null-Sicherheit. Kombiniert mit required-Eigenschaften (C# 11+):

// Nullable reference types + required properties (C# 11+)
#nullable enable

public class UserProfile
{
    public required string Name { get; init; }
    public required string Email { get; init; }
    public string? Nickname { get; init; }     // optional
    public int Age { get; init; }
    public string? AvatarUrl { get; init; }     // optional
    public required List<string> Roles { get; init; }
}

// Deserialization enforces required properties
var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};
var user = JsonSerializer.Deserialize<UserProfile>(json, options)
    ?? throw new InvalidOperationException(
        "Failed to deserialize user profile");

// Compiler warning if you forget to set required properties:
// var profile = new UserProfile { Name = "Alice" };
// Error CS9035: Required member 'Email' must be set

// JsonRequired attribute for runtime enforcement
public class StrictModel
{
    [JsonRequired]
    public string Id { get; set; } = "";

    [JsonRequired]
    public string Name { get; set; } = "";

    public string? Description { get; set; }
}

System.Text.Json vs Newtonsoft: System.Text.Json ist 2-5x schneller, braucht weniger Speicher und unterstutzt Quellgeneratoren. Newtonsoft bietet mehr Funktionen.

Best Practices fur JSON-zu-C#-Konvertierung

Befolgen Sie diese Best Practices fur robuste .NET-Anwendungen:

PascalCase-Eigenschaften mit Attributen: [JsonPropertyName] fur JSON-Key-Mapping.

Nullable-Typen aktivieren: #nullable enable fur Kompilierzeit-Null-Sicherheit.

Unbekannte Eigenschaften behandeln: System.Text.Json ignoriert sie standardmassig. Newtonsoft mit MissingMemberHandling.Ignore konfigurieren.

Decimal fur Geldwerte: Niemals float oder double fur Geld.

Records fur DTOs bevorzugen: Records mit init-only-Eigenschaften fur Unveranderlichkeit.

Quellgeneratoren fur Performance: [JsonSerializable] in .NET 8+.

Deserialisierte Daten validieren: Datenannnotationen oder FluentValidation.

Verwandte Tools: JSON zu Java, JSON zu TypeScript, JSON zu Kotlin.

JSON to JavaJSON to TypeScriptJSON to Kotlin

Haufig gestellte Fragen

System.Text.Json oder Newtonsoft: Welches soll ich verwenden?

System.Text.Json wird fur neue .NET 8+-Projekte empfohlen. Es ist integriert, 2-5x schneller und unterstutzt AOT-Quellgeneratoren. Newtonsoft bleibt nutzlich fur bestehende Projekte und komplexe JObject-Szenarien.

C# Records oder traditionelle Klassen?

Records fur unveranderliche DTOs (C# 9+). Klassen fur Veranderlichkeit oder INotifyPropertyChanged. Fur ASP.NET Core sind Records die moderne Best Practice.

Wie gehe ich mit unbekannten JSON-Eigenschaften um?

System.Text.Json ignoriert sie standardmassig. Zum Auffangen verwenden Sie [JsonExtensionData]. Newtonsoft wirft standardmassig, konfigurieren Sie MissingMemberHandling.Ignore.

Die Konvertierung von JSON zu C# ist eine grundlegende Fahigkeit. Nutzen Sie unser kostenloses Tool fur sofortige Generierung.

Konvertieren Sie JSON sofort in C#-Klassen mit unserem kostenlosen Tool.

War das hilfreich?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Partner Picks

Sponsor this article

Place your product next to this developer topic with tracked clicks.

Ask about article sponsorship

This site uses cookies for analytics and to display ads. By continuing to browse, you agree. Privacy Policy