JSON to Dart

Genereer Dart-klassen vanuit JSON met fromJson en toJson

Probeer een voorbeeld
Naam rootklasse:

JSON-invoer

Dart-uitvoer

Draait lokaal · Veilig om secrets te plakken
Dart-klassen verschijnen hier…

Wat is JSON naar Dart-conversie?

JSON naar Dart-conversie neemt een onbewerkt JSON-object en produceert Dart-klassedefinities met getypeerde velden, een benoemde constructor, een fromJson factory en een toJson methode. Dart heeft geen runtime-reflectie in Flutter (dart:mirrors is uitgeschakeld), waardoor je JSON niet kunt deserializeren naar getypeerde objecten zonder expliciete mapping-code. Elk REST API-antwoord, Firebase-document of configuratiepayload heeft een bijbehorende Dart-modelklasse nodig voordat je de velden type-veilig kunt benaderen.

Een typische Dart-modelklasse voor JSON declareert final-velden voor elke sleutel, een constructor met benoemde parameters (met het required-sleutelwoord voor niet-nullable velden), een factory-constructor genaamd fromJson die leest uit een Map van String naar dynamic, en een toJson methode die een Map van String naar dynamic retourneert. Geneste JSON-objecten worden afzonderlijke klassen. Arrays worden getypeerde List-velden. Nullable JSON-waarden gebruiken Dart's null-safety-syntax met het ?-achtervoegsel op het type.

Het handmatig schrijven van deze modelklassen vereist het lezen van elke JSON-sleutel, het bepalen van het Dart-type, het aanmaken van de fromJson-cast voor elk veld (inclusief lijstmapping met .map().toList()), het bouwen van een toJson-mapliteraal en dit herhalen voor elk genest object. Voor een JSON-object met 12 velden en 2 geneste objecten betekent dat 3 klassen, 6 factory-regels en tientallen cast-expressies. Een converter produceert dit alles in milliseconden vanuit één plakactie.

Waarom een JSON naar Dart-converter gebruiken?

Het handmatig schrijven van Dart-modelklassen vanuit JSON vereist het lezen van veldnamen, het raden van typen op basis van voorbeeldwaarden, het schrijven van fromJson-casts met correcte null-afhandeling en het herhalen van het proces voor geneste objecten. Wanneer de API-structuur verandert, raakt elke veldwijziging de constructor, fromJson én toJson. Een converter verwijdert dat repetitieve werk.

Directe klassegeneratie
Plak JSON en ontvang complete Dart-klassen met constructors, fromJson factories en toJson methoden in minder dan een seconde. Geneste objecten en lijsten worden automatisch gedetecteerd en verwerkt.
🔒
Privacy-first verwerking
De conversie verloopt volledig in je browser via JavaScript. Je JSON-gegevens verlaten je machine nooit. API-sleutels, tokens en productiegegevens blijven privé.
📝
Null-safe uitvoer
Gegenereerde klassen maken gebruik van Dart's sound null safety. Nullable JSON-velden krijgen het ?-type-achtervoegsel en slaan het required-sleutelwoord in constructors over. Niet-nullable velden zijn gemarkeerd als required.
📦
Geen installatie of account
Open de pagina en plak je JSON. Geen Dart SDK, geen pub-afhankelijkheden, geen account. Werkt op elk apparaat met een browser.

Gebruiksscenario's voor JSON naar Dart

Flutter-appontwikkeling
Genereer modelklassen voor REST API-antwoorden die worden gebruikt door de http of dio-pakketten. Plak de JSON die je backend retourneert en ontvang Dart-klassen die klaar zijn voor jsonDecode en widget-rendering.
Firebase / Firestore-integratie
Maak getypeerde modelklassen voor Firestore-documentsnapshots. Plak een voorbeelddocument als JSON, genereer de Dart-klasse en gebruik fromJson met snapshot.data() in je repository-laag.
State management-modellen
Definieer getypeerde state-objecten voor Riverpod, Bloc of Provider. Plak de verwachte state-structuur als JSON en ontvang onveranderlijke Dart-klassen met toJson voor state-persistentie en hydration.
API-clientcodegeneratie
Produceer request- en responsemodellen voor Retrofit of Chopper API-clients. Plak JSON-voorbeeldpayloads en ontvang Dart-klassen die overeenkomen met je OpenAPI-responseschema's.
Geautomatiseerd testen
Bouw getypeerde testfixtures vanuit echte API-antwoorden. Plak een JSON-voorbeeld, genereer de modelklasse en gebruik deze direct in unit- en widgettests zonder handmatig fixtures te schrijven.
Dart-patronen leren
Studenten die Flutter leren kunnen elke JSON-structuur plakken en zien hoe Dart die weergeeft: final-velden, benoemde constructors, factory fromJson-patronen en null-safety-annotaties in de praktijk.

JSON naar Dart-typemapping

Elke JSON-waarde komt overeen met een specifiek Dart-type. De onderstaande tabel toont hoe de converter elk JSON-type vertaalt. De kolom Alternatief toont typen die worden gebruikt in minder gangbare of handmatige mapping-scenario's.

JSON-typeVoorbeeldDart-typeAlternatief
string"hello"StringString
number (integer)42intint
number (float)3.14doubledouble
booleantrueboolbool
nullnulldynamicNull / dynamic
object{"k": "v"}NestedClassMap<String, dynamic>
array of strings["a", "b"]List<String>List<String>
array of objects[{"id": 1}]List<Item>List<Item>
mixed array[1, "a"]List<dynamic>List<dynamic>

Dart JSON-serialisatiebenaderingen

Dart en Flutter bieden meerdere manieren om JSON-serialisatie af te handelen. Handmatige fromJson/toJson is de eenvoudigste aanpak en vereist geen codegeneratie. Voor grotere projecten genereren op build_runner gebaseerde oplossingen zoals json_serializable en freezed de boilerplatecode tijdens het compileren, waardoor fouten worden verminderd en modellen consistent blijven met het JSON-contract.

AanpakBeschrijvingBron
json_serializableCode-generation-based JSON serialization. Generates .g.dart files at build time via build_runner. Type-safe and compile-time verified.Official (Google)
freezedGenerates immutable data classes with copyWith, fromJson/toJson, equality, and pattern matching support. Built on top of json_serializable.Community (rrousselGit)
built_valueGenerates immutable value types with serialization. Enforces immutability patterns. Used in larger codebases with strict data modeling.Google
dart_mappableAnnotation-based mapper that generates fromJson, toJson, copyWith, and equality. Simpler setup than freezed with similar features.Community
Manual fromJson/toJsonHand-written factory constructors and toJson methods. No code generation needed. Full control over the mapping logic.Built-in Dart

Handmatig vs json_serializable vs freezed

Dart heeft drie gangbare benaderingen voor JSON-modelklassen. Handmatige fromJson/toJson heeft geen afhankelijkheden. json_serializable automatiseert de mapping-code. freezed voegt onveranderlijkheid, copyWith en patroonmatching toe bovenop json_serializable.

Manual fromJson/toJson
Schrijf fromJson factories en toJson methoden handmatig. Geen afhankelijkheden, geen build_runner-stap. Je hebt volledige controle over de cast-logica en foutafhandeling. Het meest geschikt voor kleine projecten met een beperkt aantal modellen, of wanneer je aangepaste deserialisatie nodig hebt die codegeneratoren niet kunnen uitdrukken. Dit is het uitvoerformaat dat dit gereedschap genereert.
json_serializable
Annoteer je klasse met @JsonSerializable() en voer dart run build_runner build uit. De generator maakt een .g.dart-bestand aan met _$ClassFromJson en _$ClassToJson functies. Verwerkt @JsonKey voor hernoeming van velden, standaardwaarden en aangepaste converters. De standaardkeuze voor middelgrote tot grote Flutter-projecten.
freezed
Annoteer met @freezed en ontvang onveranderlijke klassen met fromJson, toJson, copyWith, gelijkheid (== en hashCode) en toString die automatisch worden gegenereerd. Ondersteunt union-typen voor sealed class-patronen. Vereist zowel freezed als json_serializable als dev-afhankelijkheden. Het meest geschikt voor state management-modellen en complexe domeinobjecten.

Codevoorbeelden

Deze voorbeelden tonen hoe gegenereerde Dart-klassen worden gebruikt voor JSON-deserialisatie, hoe json_serializable wordt ingesteld met build_runner en hoe Dart-klassen programmatisch worden gegenereerd vanuit JavaScript en Python.

Dart (manual fromJson / toJson)
import 'dart:convert';

class User {
  final int id;
  final String name;
  final String email;
  final bool active;
  final Address address;
  final List<String> tags;

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

  factory User.fromJson(Map<String, dynamic> json) => User(
    id: json['id'] as int,
    name: json['name'] as String,
    email: json['email'] as String,
    active: json['active'] as bool,
    address: Address.fromJson(json['address'] as Map<String, dynamic>),
    tags: (json['tags'] as List<dynamic>).map((e) => e as String).toList(),
  );

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

class Address {
  final String street;
  final String city;
  final String zip;

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

  factory Address.fromJson(Map<String, dynamic> json) => Address(
    street: json['street'] as String,
    city: json['city'] as String,
    zip: json['zip'] as String,
  );

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

void main() {
  final jsonStr = '{"id":1,"name":"Alice","email":"alice@example.com","active":true,"address":{"street":"123 Main","city":"Springfield","zip":"12345"},"tags":["admin","user"]}';
  final user = User.fromJson(jsonDecode(jsonStr));
  print(user.name); // -> Alice
  print(jsonEncode(user.toJson())); // -> round-trip back to JSON
}
Dart (json_serializable + build_runner)
// pubspec.yaml dependencies:
//   json_annotation: ^4.8.0
//   dev_dependencies:
//     build_runner: ^2.4.0
//     json_serializable: ^6.7.0

import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart'; // generated by: dart run build_runner build

@JsonSerializable()
class User {
  final int id;
  final String name;
  final String email;
  @JsonKey(name: 'is_active')
  final bool isActive;
  final List<String> tags;

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

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

// Run code generation:
// dart run build_runner build --delete-conflicting-outputs
JavaScript (generate Dart classes from JSON)
function jsonToDart(obj, name = "Root") {
  const classes = [];
  function infer(val, fieldName) {
    if (val === null) return "dynamic";
    if (typeof val === "string") return "String";
    if (typeof val === "number") return Number.isInteger(val) ? "int" : "double";
    if (typeof val === "boolean") return "bool";
    if (Array.isArray(val)) {
      const first = val.find(v => v !== null);
      if (!first) return "List<dynamic>";
      return `List<${infer(first, fieldName)}>`;
    }
    if (typeof val === "object") {
      const cls = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
      build(val, cls);
      return cls;
    }
    return "dynamic";
  }
  function build(obj, cls) {
    const fields = Object.entries(obj).map(([k, v]) =>
      `  final ${infer(v, k)} ${k};`
    );
    classes.push(`class ${cls} {\n${fields.join("\n")}\n}`);
  }
  build(obj, name);
  return classes.join("\n\n");
}

console.log(jsonToDart({ id: 1, name: "Alice", scores: [98, 85] }, "User"));
// class User {
//   final int id;
//   final String name;
//   final List<int> scores;
// }
Python (generate Dart model from JSON)
import json

def json_to_dart(obj: dict, class_name: str = "Root") -> str:
    classes = []

    def infer(val, name):
        if val is None:
            return "dynamic"
        if isinstance(val, bool):
            return "bool"
        if isinstance(val, int):
            return "int"
        if isinstance(val, float):
            return "double"
        if isinstance(val, str):
            return "String"
        if isinstance(val, list):
            if not val:
                return "List<dynamic>"
            return f"List<{infer(val[0], name)}>"
        if isinstance(val, dict):
            cls = name[0].upper() + name[1:]
            build(val, cls)
            return cls
        return "dynamic"

    def build(obj, cls):
        fields = [f"  final {infer(v, k)} {k};" for k, v in obj.items()]
        classes.append(f"class {cls} {{\n" + "\n".join(fields) + "\n}")

    build(obj, class_name)
    return "\n\n".join(classes)

data = json.loads('{"id": 1, "name": "Alice", "active": true}')
print(json_to_dart(data, "User"))
# class User {
#   final int id;
#   final String name;
#   final bool active;
# }

Veelgestelde vragen

Waarom kan Flutter dart:mirrors niet gebruiken voor JSON-deserialisatie?
Flutter schakelt dart:mirrors (de reflectiebibliotheek) uit omdat tree-shaking vereist dat tijdens het compileren bekend is welke code wordt gebruikt. Reflectie zou voorkomen dat de compiler ongebruikte klassen verwijdert, waardoor de appgrootte toeneemt. Daarom hebben Flutter-projecten expliciete fromJson/toJson methoden of codegeneratie nodig in plaats van runtime-reflectie.
Moet ik json_serializable gebruiken of fromJson handmatig schrijven?
Voor projecten met minder dan 10 modelklassen is handgeschreven fromJson/toJson eenvoudig en voegt het geen bouwafhankelijkheden toe. Zodra je meer dan 10 modellen hebt, of modellen die regelmatig wijzigen, bespaart json_serializable tijd en vermindert het kopieer-plakfouten. De mapping-code wordt gegenereerd vanuit annotaties, zodat veldtoevoegingen alleen vereisen dat build_runner opnieuw wordt uitgevoerd.
Hoe verwerkt de converter geneste JSON-objecten?
Elk genest JSON-object wordt een afzonderlijke Dart-klasse. Als een JSON-veld genaamd "address" een object bevat met "street" en "city" sleutels, maakt de converter een Address-klasse aan met die velden en typeert het bovenliggende veld als Address. De fromJson factory cast de geneste map en geeft deze door aan Address.fromJson.
Wat gebeurt er als een JSON-veld null is?
Null-velden worden getypeerd als dynamic met een ?-achtervoegsel, omdat de converter het beoogde type niet kan bepalen uit een null-waarde alleen. Vervang dynamic? door het juiste type (String?, int?, etc.) zodra je dat kent uit je API-contract. Dart's null safety handhaaft dan correcte null-controles tijdens het compileren.
Hoe ga ik om met JSON-sleutels die geen geldige Dart-identifiers zijn?
JSON-sleutels zoals "first-name" of "2nd_place" zijn geen geldige Dart-veldnamen. Met handmatige fromJson kun je elke JSON-sleutel koppelen aan elke Dart-veldnaam in de factory-constructor. Met json_serializable gebruik je @JsonKey(name: 'first-name') om het veld te annoteren. De converter converteert sleutelnamen automatisch naar camelCase Dart-velden.
Kan ik freezed gebruiken met de uitvoer van dit gereedschap?
Het gereedschap genereert standaard Dart-klassen met handmatige fromJson/toJson. Om te converteren naar freezed, wijzig je de klasse zodat deze de @freezed-annotatie gebruikt, verwijder je de handgeschreven constructor en factory, en voeg je de freezed-mixin toe. Voer vervolgens build_runner uit om de .freezed.dart en .g.dart bestanden te genereren. De veldnamen en typen uit de gegenereerde uitvoer worden direct overgenomen.
Wat is het verschil tussen een onbewerkte map en een getypeerde Dart-klasse voor JSON?
Een onbewerkte map (Map van String naar dynamic) geeft je directe toegang tot JSON-gegevens zonder typecontrole. Je moet elke waarde casten op de aanroeplocatie, en typefouten in sleutelnamen mislukken stil tijdens runtime. Een getypeerde Dart-klasse vangt typemismatches op bij de fromJson-grens, biedt IDE-autoaanvulling voor veldnamen en maakt refactoring veilig. Het prestatieverschil is verwaarloosbaar; het voordeel betreft uitsluitend correctheid en onderhoudbaarheid.