JSON'dan Dart'a

JSON'dan fromJson ve toJson ile Dart sınıfları oluşturun

Örnek dene
Kök sınıf adı:

JSON Girişi

Dart Çıktısı

Yerel olarak çalışır · Gizli bilgi yapıştırmak güvenlidir
Dart sınıfları burada görünecek…

JSON'dan Dart'a Dönüşüm Nedir?

JSON'dan Dart'a dönüşüm, ham bir JSON nesnesini alır ve tiplendirilmiş alanlar, adlandırılmış bir yapıcı, fromJson factory ve toJson metodu içeren Dart sınıf tanımları üretir. Dart'ın Flutter'da çalışma zamanı yansıması yoktur (dart:mirrors devre dışı bırakılmıştır); bu nedenle açık eşleme kodu yazmadan JSON'u tiplendirilmiş nesnelere dönüştüremezsiniz. Her REST API yanıtı, Firebase belgesi veya yapılandırma yükü için tip güvenliğiyle alanlara erişebilmek üzere karşılık gelen bir Dart model sınıfı gerekir.

JSON için tipik bir Dart model sınıfı, her anahtar için final alanlar, adlandırılmış parametreli bir yapıcı (null olamayan alanlar için required anahtar kelimesi kullanılarak), Map of String to dynamic okuyan fromJson adlı bir factory yapıcı ve Map of String to dynamic döndüren bir toJson metodu içerir. İç içe JSON nesneleri ayrı sınıflara dönüşür. Diziler tiplendirilmiş List alanlarına dönüşür. Nullable JSON değerleri, türün sonuna ? ekiyle Dart'ın null-safety söz dizimini kullanır.

Bu model sınıflarını elle yazmak; her JSON anahtarını okumayı, Dart türüne karar vermeyi, her alan için fromJson dönüşümü oluşturmayı (.map().toList() ile liste eşleme dahil), toJson map literalini oluşturmayı ve iç içe her nesne için bu işlemi tekrarlamayı gerektirir. 12 alanlı ve 2 iç içe nesneli bir JSON nesnesi için bu 3 sınıf, 6 factory satırı ve düzinelerce dönüşüm ifadesi anlamına gelir. Bir dönüştürücü tek bir yapıştırmayla tüm bunları milisaniyeler içinde üretir.

Neden JSON'dan Dart'a Dönüştürücü Kullanmalısınız?

Dart model sınıflarını JSON'dan elle yazmak; alan adlarını okumayı, örnek değerlerden türleri tahmin etmeyi, doğru null işlemeyle fromJson dönüşümleri yazmayı ve iç içe nesneler için işlemi tekrarlamayı gerektirir. API yapısı değiştiğinde her alan güncellemesi yapıcıya, fromJson'a ve toJson'a dokunur. Bir dönüştürücü bu tekrarlayan işi ortadan kaldırır.

Anlık sınıf üretimi
JSON'u yapıştırın ve bir saniyeden kısa sürede yapıcılar, fromJson factory'ler ve toJson metodlarıyla birlikte eksiksiz Dart sınıfları alın. İç içe nesneler ve listeler otomatik olarak algılanır ve eşlenir.
🔒
Gizlilik öncelikli işleme
Dönüşüm tamamen tarayıcınızda JavaScript kullanılarak çalışır. JSON veriniz asla makinenizden çıkmaz. API anahtarları, tokenlar ve üretim yükleri gizli kalır.
📝
Null-safe çıktı
Oluşturulan sınıflar Dart'ın sağlam null safety özelliğini kullanır. Nullable JSON alanları ? tür ekini alır ve yapıcılarda required anahtar kelimesini atlar. Null olamayan alanlar required olarak işaretlenir.
📦
Kurulum veya kayıt gerekmez
Sayfayı açın ve JSON'unuzu yapıştırın. Dart SDK, pub bağımlılığı veya hesap gerekmez. Tarayıcısı olan her cihazda çalışır.

JSON'dan Dart'a Kullanım Senaryoları

Flutter Uygulama Geliştirme
http veya dio paketleri tarafından tüketilen REST API yanıtları için model sınıfları oluşturun. Backend'inizin döndürdüğü JSON'u yapıştırın ve jsonDecode ile widget render işlemine hazır Dart sınıfları alın.
Firebase / Firestore Entegrasyonu
Firestore belge anlık görüntüleri için tiplendirilmiş model sınıfları oluşturun. Örnek bir belgeyi JSON olarak yapıştırın, Dart sınıfını oluşturun ve depo katmanınızda snapshot.data() ile fromJson kullanın.
State Management Modelleri
Riverpod, Bloc veya Provider için tiplendirilmiş durum nesneleri tanımlayın. Beklenen durum şeklini JSON olarak yapıştırın ve durum kalıcılığı ve hidrasyonu için toJson ile birlikte değiştirilemez Dart sınıfları alın.
API İstemci Kod Üretimi
Retrofit veya Chopper API istemcileri için istek ve yanıt modelleri oluşturun. Örnek JSON yüklerini yapıştırın ve OpenAPI yanıt şemalarınızla eşleşen Dart sınıfları alın.
Otomatik Test
Gerçek API yanıtlarından tiplendirilmiş test fixture'ları oluşturun. Bir JSON örneği yapıştırın, model sınıfını oluşturun ve fixture yapılarını elle yazmadan doğrudan birim ve widget testlerinde kullanın.
Dart Kalıplarını Öğrenme
Flutter öğrenen öğrenciler herhangi bir JSON yapısını yapıştırabilir ve Dart'ın bunu nasıl temsil ettiğini görebilir: final alanlar, adlandırılmış yapıcılar, factory fromJson kalıpları ve pratikte null-safety anotasyonları.

JSON'dan Dart'a Tür Eşleme

Her JSON değeri belirli bir Dart türüne eşlenir. Aşağıdaki tablo, dönüştürücünün her JSON türünü nasıl çevirdiğini göstermektedir. Alternatif sütunu, daha az yaygın veya manuel eşleme senaryolarında kullanılan türleri gösterir.

JSON TürüÖrnekDart TürüAlternatif
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 Serileştirme Yaklaşımları

Dart ve Flutter, JSON serileştirmeyi ele almak için birden fazla yol sunar. Manuel fromJson/toJson en basit yaklaşımdır ve kod üretimi gerektirmez. Daha büyük projeler için json_serializable ve freezed gibi build_runner tabanlı çözümler, derleme zamanında gerekli kodu oluşturarak hataları azaltır ve modelleri JSON sözleşmesiyle tutarlı tutar.

YaklaşımAçıklamaKaynak
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

Manuel vs json_serializable vs freezed

Dart'ın JSON model sınıfları için üç yaygın yaklaşımı vardır. Manuel fromJson/toJson sıfır bağımlılıkla çalışır. json_serializable eşleme kodunu otomatikleştirir. freezed, json_serializable'ın üzerine değiştirilemezlik, copyWith ve örüntü eşleştirme ekler.

Manual fromJson/toJson
fromJson factory'leri ve toJson metodlarını elle yazın. Sıfır bağımlılık, build_runner adımı yok. Dönüşüm mantığı ve hata işleme üzerinde tam kontrole sahipsiniz. Az sayıda modeli olan küçük projeler veya kod üreteçlerinin ifade edemediği özel seri dışı bırakma gerektiren durumlar için en iyisidir. Bu araç bu çıktı biçimini üretir.
json_serializable
Sınıfınıza @JsonSerializable() anotasyonu ekleyin ve dart run build_runner build komutunu çalıştırın. Üretici, _$ClassFromJson ve _$ClassToJson fonksiyonlarını içeren bir .g.dart dosyası oluşturur. Alan yeniden adlandırma, varsayılan değerler ve özel dönüştürücüler için @JsonKey'i destekler. Orta ve büyük ölçekli Flutter projeleri için standart seçim.
freezed
@freezed anotasyonuyla fromJson, toJson, copyWith, eşitlik (== ve hashCode) ve toString'in otomatik olarak oluşturulduğu değiştirilemez sınıflar elde edin. Sealed class kalıpları için union türlerini destekler. Hem freezed hem de json_serializable'ı geliştirme bağımlılığı olarak gerektirir. State management modelleri ve karmaşık domain nesneleri için en iyisidir.

Kod Örnekleri

Bu örnekler, JSON seri dışı bırakma için oluşturulan Dart sınıflarının nasıl kullanılacağını, build_runner ile json_serializable'ın nasıl kurulacağını ve JavaScript ile Python'dan programatik olarak Dart sınıflarının nasıl oluşturulacağını göstermektedir.

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

Sık Sorulan Sorular

Flutter neden JSON seri dışı bırakma için dart:mirrors kullanamıyor?
Flutter, dart:mirrors'ı (yansıma kütüphanesi) devre dışı bırakır çünkü tree-shaking, derleme zamanında hangi kodun kullanıldığını bilmeyi gerektirir. Yansıma, derleyicinin kullanılmayan sınıfları kaldırmasını engelleyerek uygulama boyutunu artırır. Bu nedenle Flutter projeleri, çalışma zamanı yansıması yerine açık fromJson/toJson metodları veya kod üretimi kullanmalıdır.
json_serializable mı kullanmalıyım yoksa fromJson'u elle mi yazmalıyım?
10'dan az model sınıfı olan projeler için elle yazılan fromJson/toJson yeterlidir ve derleme bağımlılığı eklemez. 10'dan fazla model olduğunda veya modeller sık değiştiğinde json_serializable zaman kazandırır ve kopyala-yapıştır hatalarını azaltır. Eşleme kodunu anotasyonlardan üretir; dolayısıyla alan eklemeleri yalnızca build_runner'ı yeniden çalıştırmayı gerektirir.
Dönüştürücü iç içe JSON nesnelerini nasıl işler?
Her iç içe JSON nesnesi ayrı bir Dart sınıfına dönüşür. "address" adlı bir JSON alanı "street" ve "city" anahtarlarına sahip bir nesne içeriyorsa, dönüştürücü bu alanlarla bir Address sınıfı oluşturur ve üst alanı Address olarak tiplendirir. fromJson factory, iç içe map'i dönüştürür ve Address.fromJson'a iletir.
Bir JSON alanı null olduğunda ne olur?
Null alanlar, ? ekiyle dynamic olarak tiplendirilir; çünkü dönüştürücü yalnızca null değerden amaçlanan türü belirleyemez. API sözleşmenizden öğrendikten sonra dynamic? yerine doğru türü (String?, int? vb.) kullanın. Dart'ın null safety özelliği, derleme zamanında doğru null denetimlerini zorunlu kılar.
Geçerli Dart tanımlayıcısı olmayan JSON anahtarlarını nasıl işlerim?
"first-name" veya "2nd_place" gibi JSON anahtarları geçerli Dart alan adları değildir. Manuel fromJson ile factory yapıcıda herhangi bir JSON anahtarını herhangi bir Dart alan adıyla eşleyebilirsiniz. json_serializable ile alanı anotasyonlamak için @JsonKey(name: 'first-name') kullanın. Dönüştürücü, anahtar adlarını otomatik olarak camelCase Dart alanlarına dönüştürür.
Bu araçtan alınan çıktıyla freezed kullanabilir miyim?
Araç, manuel fromJson/toJson ile standart Dart sınıfları oluşturur. freezed'e geçmek için sınıfı @freezed anotasyonunu kullanacak şekilde değiştirin, elle yazılan yapıcı ve factory'yi kaldırın ve freezed mixin'ini ekleyin. Ardından .freezed.dart ve .g.dart dosyalarını oluşturmak için build_runner çalıştırın. Oluşturulan çıktıdaki alan adları ve türler doğrudan aktarılır.
Ham map ile tiplendirilmiş Dart sınıfı arasındaki fark nedir?
Ham bir map (Map of String to dynamic), tür denetimi olmadan JSON verilerine ham erişim sağlar. Her değeri çağrı noktasında dönüştürmeniz gerekir; anahtar adlarındaki yazım hataları çalışma zamanında sessizce başarısız olur. Tiplendirilmiş bir Dart sınıfı, fromJson sınırında tür uyumsuzluklarını yakalar, alan adları için IDE otomatik tamamlaması sağlar ve yeniden düzenlemeyi güvenli kılar. Performans farkı göz ardı edilebilir düzeydedir; asıl fayda doğruluk ve sürdürülebilirlik açısındandır.