JSON to Dart

Generování Dart tříd z JSON s fromJson a toJson

Zkusit příklad
Název kořenové třídy:

Vstup JSON

Výstup Dart

Běží lokálně · Bezpečné pro vkládání tajných údajů
Dart třídy se zobrazí zde…

Co je převod JSON na Dart?

Převod JSON na Dart vezme surový JSON objekt a vytvoří definice Dart tříd s typovanými poli, pojmenovaným konstruktorem, továrnou fromJson a metodou toJson. Dart nemá v Flutteru runtime reflexi (dart:mirrors je zakázán), takže nelze deserializovat JSON do typovaných objektů bez explicitního mapovacího kódu. Každá REST API odpověď, Firestore dokument nebo konfigurační payload potřebuje odpovídající Dart třídu, než lze k polím přistupovat s typovou bezpečností.

Typická Dart třída modelu pro JSON deklaruje final pole pro každý klíč, konstruktor s pojmenovanými parametry (klíčové slovo required pro non-nullable pole), tovární konstruktor fromJson čtoucí z Map<String, dynamic> a metodu toJson vracející Map<String, dynamic>. Vnořené JSON objekty se stávají samostatnými třídami. Pole se stávají typovanými poli List<T>. Nullable JSON hodnoty používají syntaxi null-safety s příponou ? za typem.

Ruční psaní těchto tříd modelů znamená číst každý JSON klíč, rozhodovat o Dart typu, vytvářet fromJson přetypování pro každé pole (včetně mapování seznamů přes .map().toList()), sestavovat mapový literál toJson a opakovat vše pro každý vnořený objekt. Pro JSON objekt s 12 poli a 2 vnořenými objekty to znamená 3 třídy, 6 továrních řádků a desítky přetypovacích výrazů. Převodník vše vyprodukuje v milisekundách z jediného vložení.

Proč používat převodník JSON na Dart?

Ruční vytváření Dart tříd modelů z JSON zahrnuje čtení názvů polí, odvozování typů z ukázkových hodnot, psaní fromJson přetypování se správným ošetřením null a opakování celého procesu pro vnořené objekty. Když se tvar API změní, každá aktualizace pole se dotkne konstruktoru, fromJson i toJson. Převodník tuto opakující se práci odstraní.

Okamžité generování tříd
Vložte JSON a získejte kompletní Dart třídy s konstruktory, továrnami fromJson a metodami toJson za méně než sekundu. Vnořené objekty a seznamy jsou automaticky detekovány a namapovány.
🔒
Zpracování s ochranou soukromí
Převod probíhá celý ve vašem prohlížeči pomocí JavaScriptu. Vaše JSON data nikdy neopustí vaše zařízení. API klíče, tokeny a produkční payloady zůstávají soukromé.
📝
Výstup s null-safety
Generované třídy používají Dartovu zvukovou null-safety. Nullable JSON pole dostávají příponu ? za typem a vynechávají klíčové slovo required v konstruktorech. Non-null pole jsou označena jako required.
📦
Bez instalace nebo registrace
Otevřete stránku a vložte JSON. Žádné Dart SDK, žádné pub závislosti, žádný účet. Funguje na jakémkoli zařízení s prohlížečem.

Případy použití JSON na Dart

Vývoj Flutter aplikací
Generujte třídy modelů pro REST API odpovědi konzumované balíčky http nebo dio. Vložte JSON vrácený vaším backendem a získejte Dart třídy připravené pro jsonDecode a vykreslování widgetů.
Integrace Firebase / Firestore
Vytvářejte typované třídy modelů pro snímky Firestore dokumentů. Vložte ukázkový dokument jako JSON, vygenerujte Dart třídu a použijte fromJson se snapshot.data() ve vrstvě repozitáře.
Modely pro správu stavu
Definujte typované objekty stavů pro Riverpod, Bloc nebo Provider. Vložte očekávaný tvar stavu jako JSON a získejte neměnitelné Dart třídy s toJson pro persistenci a hydrataci stavu.
Generování kódu API klienta
Vytvářejte modely požadavků a odpovědí pro API klienty Retrofit nebo Chopper. Vložte ukázkové JSON payloady a získejte Dart třídy odpovídající vašim OpenAPI schématům odpovědí.
Automatizované testování
Sestavujte typovaná testovací data z reálných API odpovědí. Vložte JSON ukázku, vygenerujte třídu modelu a použijte ji přímo v unit a widget testech bez ručního psaní datových struktur.
Učení Dart vzorů
Studenti učící se Flutter mohou vložit libovolnou JSON strukturu a vidět, jak ji Dart reprezentuje: final pole, pojmenované konstruktory, tovární vzory fromJson a anotace null-safety v praxi.

Mapování typů JSON na Dart

Každá JSON hodnota se mapuje na konkrétní Dart typ. Tabulka níže ukazuje, jak převodník překládá každý JSON typ. Sloupec Alternativa zobrazuje typy používané v méně obvyklých nebo ručních mapovacích scénářích.

Typ JSONPříkladTyp DartAlternativa
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>

Přístupy k JSON serializaci v Dartu

Dart a Flutter nabízejí více způsobů zpracování JSON serializace. Ruční fromJson/toJson je nejjednodušší přístup a nevyžaduje generování kódu. Pro větší projekty řešení založená na build_runner, jako json_serializable a freezed, generují šablonový kód při kompilaci, snižují chyby a udržují modely konzistentní s JSON kontraktem.

PřístupPopisZdroj
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

Ruční vs json_serializable vs freezed

Dart má tři běžné přístupy pro JSON třídy modelů. Ruční fromJson/toJson nemá žádné závislosti. json_serializable automatizuje mapovací kód. freezed přidává neměnitelnost, copyWith a porovnávání vzorů na základě json_serializable.

Manual fromJson/toJson
Ručně pište továrny fromJson a metody toJson. Žádné závislosti, žádný krok s build_runner. Máte plnou kontrolu nad logikou přetypování a ošetřením chyb. Nejlepší pro malé projekty s několika málo modely nebo když potřebujete vlastní deserializaci, kterou generátory kódu neumí vyjádřit. Toto je výstupní formát generovaný tímto nástrojem.
json_serializable
Anotujte třídu pomocí @JsonSerializable() a spusťte dart run build_runner build. Generátor vytvoří soubor .g.dart s funkcemi _$ClassFromJson a _$ClassToJson. Zpracovává @JsonKey pro přejmenování polí, výchozí hodnoty a vlastní konvertory. Standardní volba pro středně velké až velké Flutter projekty.
freezed
Anotujte pomocí @freezed a získejte neměnitelné třídy s automaticky generovanými fromJson, toJson, copyWith, rovností (== a hashCode) a toString. Podporuje union typy pro vzory zapečetěných tříd. Vyžaduje freezed i json_serializable jako vývojové závislosti. Nejlepší pro modely správy stavu a komplexní doménové objekty.

Příklady kódu

Tyto příklady ukazují, jak používat generované Dart třídy pro deserializaci JSON, jak nastavit json_serializable s build_runner a jak programově generovat Dart třídy z JavaScriptu a Pythonu.

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;
# }

Časté dotazy

Proč Flutter nemůže používat dart:mirrors pro deserializaci JSON?
Flutter zakazuje dart:mirrors (knihovnu reflexe), protože tree-shaking vyžaduje znát při kompilaci, který kód je používán. Reflexe by bránila kompilátoru odstraňovat nepoužívané třídy a zvyšovala by velikost aplikace. Proto Flutter projekty potřebují explicitní metody fromJson/toJson nebo generování kódu namísto runtime reflexe.
Mám použít json_serializable nebo psát fromJson ručně?
Pro projekty s méně než 10 třídami modelů je ruční fromJson/toJson přímočaré a nepřidává žádné závislosti sestavení. Jakmile máte více než 10 modelů nebo modely, které se často mění, json_serializable šetří čas a snižuje chyby způsobené kopírováním. Generuje mapovací kód z anotací, takže přidání pole vyžaduje pouze opětovné spuštění build_runner.
Jak převodník zpracovává vnořené JSON objekty?
Každý vnořený JSON objekt se stane samostatnou Dart třídou. Pokud JSON pole s názvem "address" obsahuje objekt s klíči "street" a "city", převodník vytvoří třídu Address s těmito poli a nadřazené pole typuje jako Address. Továrna fromJson přetypuje vnořenou mapu a předá ji do Address.fromJson.
Co se stane, když je JSON pole null?
Null pole jsou typována jako dynamic s příponou ?, protože převodník nemůže odvodit zamýšlený typ pouze z hodnoty null. Nahraďte dynamic? správným typem (String?, int? atd.), jakmile znáte API kontrakt. Dartova null-safety pak vynutí správné null kontroly při kompilaci.
Jak zacházet s JSON klíči, které nejsou platnými Dart identifikátory?
JSON klíče jako "first-name" nebo "2nd_place" nejsou platnými názvy Dart polí. Při ručním fromJson lze mapovat libovolný JSON klíč na libovolný název Dart pole v továrním konstruktoru. Při json_serializable použijte @JsonKey(name: 'first-name') k anotaci pole. Převodník automaticky převádí názvy klíčů na camelCase Dart pole.
Mohu použít freezed s výstupem tohoto nástroje?
Nástroj generuje standardní Dart třídy s ručním fromJson/toJson. Pro převod na freezed změňte třídu tak, aby používala anotaci @freezed, odstraňte ručně psaný konstruktor a továrnu a přidejte mixin freezed. Pak spusťte build_runner pro vygenerování souborů .freezed.dart a .g.dart. Názvy a typy polí z vygenerovaného výstupu se přenesou přímo.
Jaký je rozdíl mezi raw mapou a typovanou Dart třídou pro JSON?
Raw mapa (Map<String, dynamic>) poskytuje přímý přístup k JSON datům bez typové kontroly. Každou hodnotu musíte přetypovat na místě volání a překlepy v názvech klíčů selžou tiše za runtime. Typovaná Dart třída zachycuje neshody typů na hranici fromJson, poskytuje automatické doplňování názvů polí v IDE a dělá refaktoring bezpečným. Výkonnostní rozdíl je zanedbatelný; přínos spočívá zcela ve správnosti a udržovatelnosti.