DevToolBoxFREE
BlogAdvertise

JSON zu Dart: Vollständiger Flutter Model-Klassen Guide

10 Min. Lesezeitvon DevToolBox

Die Konvertierung von JSON in Dart Model-Klassen ist eine der häufigsten Aufgaben in der Flutter-Entwicklung.

Warum Model-Klassen

Grundlegende JSON-zu-Dart-Typzuordnung

JSON-TypDart-TypBeispiel
stringString"hello" → "hello"
number (int)int42 → 42
number (float)double3.14 → 3.14
booleanbooltrue → true
nullNull / dynamicnull → null
arrayList<T>[1,2,3] → [1,2,3]
objectMap / Class{} → User()

Manuelle Model-Klasse (fromJson / toJson)

Der einfachste Ansatz ist, Model-Klassen von Hand zu schreiben:

// JSON input
{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "isActive": true,
  "score": 95.5
}

// Dart model class
class User {
  final int id;
  final String name;
  final String email;
  final bool isActive;
  final double score;

  User({
    required this.id,
    required this.name,
    required this.email,
    required this.isActive,
    required this.score,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      email: json['email'] as String,
      isActive: json['isActive'] as bool,
      score: (json['score'] as num).toDouble(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
      'isActive': isActive,
      'score': score,
    };
  }
}

Verschachtelte Objekte behandeln

Erstellen Sie separate Dart-Klassen für jede Verschachtelungsebene:

// JSON with nested object
{
  "id": 1,
  "name": "John",
  "address": {
    "street": "123 Main St",
    "city": "Springfield",
    "zipCode": "62701"
  }
}

// Dart classes
class Address {
  final String street;
  final String city;
  final String zipCode;

  Address({required this.street, required this.city, required this.zipCode});

  factory Address.fromJson(Map<String, dynamic> json) {
    return Address(
      street: json['street'] as String,
      city: json['city'] as String,
      zipCode: json['zipCode'] as String,
    );
  }

  Map<String, dynamic> toJson() => {
    'street': street, 'city': city, 'zipCode': zipCode,
  };
}

class User {
  final int id;
  final String name;
  final Address address;

  User({required this.id, required this.name, required this.address});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      address: Address.fromJson(json['address'] as Map<String, dynamic>),
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id, 'name': name, 'address': address.toJson(),
  };
}

Listen und Arrays behandeln

JSON-Arrays werden zu Dart-List-Typen:

// JSON with arrays
{
  "name": "John",
  "hobbies": ["coding", "reading", "gaming"],
  "orders": [
    {"id": 1, "product": "Laptop", "price": 999.99},
    {"id": 2, "product": "Mouse", "price": 29.99}
  ]
}

// Dart
class User {
  final String name;
  final List<String> hobbies;
  final List<Order> orders;

  User({required this.name, required this.hobbies, required this.orders});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      hobbies: List<String>.from(json['hobbies'] as List),
      orders: (json['orders'] as List)
          .map((e) => Order.fromJson(e as Map<String, dynamic>))
          .toList(),
    );
  }
}

Null Safety Best Practices

Mit Darts Null Safety müssen nullable Felder korrekt behandelt werden:

  • Verwenden Sie `required` für Pflichtfelder
  • Verwenden Sie `?` für nullable Typen
  • Standardwerte mit `??` bereitstellen
  • `late` nur verwenden wenn Initialisierung sicher ist
class User {
  final int id;
  final String name;
  final String? bio;        // nullable
  final String avatarUrl;   // with default

  User({
    required this.id,
    required this.name,
    this.bio,
    this.avatarUrl = 'https://example.com/default-avatar.png',
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
      bio: json['bio'] as String?,
      avatarUrl: json['avatarUrl'] as String? ?? 'https://example.com/default-avatar.png',
    );
  }
}

json_serializable verwenden

Für größere Projekte automatisiert json_serializable den Boilerplate-Code:

Schritt 1: Dependencies hinzufügen

# pubspec.yaml
dependencies:
  json_annotation: ^4.8.1

dev_dependencies:
  json_serializable: ^6.7.1
  build_runner: ^2.4.6

Schritt 2: Model mit Annotationen erstellen

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User {
  final int id;
  final String name;
  final String email;

  @JsonKey(name: 'is_active')
  final bool isActive;

  @JsonKey(defaultValue: 0.0)
  final double score;

  User({
    required this.id,
    required this.name,
    required this.email,
    required this.isActive,
    required this.score,
  });

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

Schritt 3: Build Runner ausführen

dart run build_runner build --delete-conflicting-outputs

Freezed für unveränderliche Models

Das freezed-Paket generiert unveränderliche Klassen mit copyWith und JSON-Serialisierung:

import 'package:freezed_annotation/freezed_annotation.dart';

part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
  const factory User({
    required int id,
    required String name,
    required String email,
    @Default(false) bool isActive,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

Häufige Fehler und Lösungen

FehlerLösung
`json['key']` ohne Null-Check`json['key'] as String? ?? ''` verwenden
Verschachtelte Objekte vergessen`NestedClass.fromJson()` aufrufen
`int` für alle Zahlen`num` verwenden und konvertieren
Fehlende Schlüssel nicht behandeln`containsKey()` oder Standardwerte verwenden
Falscher Typ in toJsonVerschachtelte Objekte rufen `.toJson()` auf

FAQ

Was ist der beste Weg JSON in Dart-Klassen umzuwandeln?

Kleine Projekte: manuell. Große Projekte: json_serializable oder freezed.

Wie behandle ich dynamische JSON-Schlüssel?

Verwenden Sie Map<String, dynamic>.

json_serializable oder freezed?

json_serializable für einfache Serialisierung, freezed für Unveränderlichkeit.

Wie behandle ich Datumsangaben?

DateTime.parse() für ISO 8601-Strings verwenden.

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