dartjsonapiMahir4 mnt baca

JSON dengan dart:convert

Encode/decode JSON: dari API ke objek dan sebaliknya.

Bahasa universal data

Hampir semua API berbicara JSON: format teks ringan untuk pertukaran data. Di Dart, JSON dipetakan ke Map<String, dynamic> dan List<dynamic>, dan library dart:convert adalah penerjemahnya.

Analogi: JSON itu seperti bahasa Inggris di bandara internasional. Sistem berbeda (server Python, aplikasi Dart) berkomunikasi lewat "bahasa" yang sama-sama dipahami.

Kenapa JSON penting?

Karena tanpa JSON skill, aplikasimu terisolasi: tidak bisa ambil data API, tidak bisa simpan konfigurasi, tidak bisa bicara dengan backend. JSON adalah gerbang integrasi.

Decode: JSON string → Dart

dart
import 'dart:convert';

void main() {
  String jsonStr = '''
  {
    "nama": "Budi",
    "umur": 17,
    "hobi": ["membaca", "ngoding"],
    "aktif": true
  }
  ''';

  // jsonDecode: string -> Map<String, dynamic>
  var data = jsonDecode(jsonStr);

  print(data['nama']); // Budi
  print(data['hobi'][0]); // membaca
  print(data['umur'].runtimeType); // int (otomatis!)

  // Aman dengan cast eksplisit
  Map<String, dynamic> user = jsonDecode(jsonStr);
  String nama = user['nama'] as String;
  print('Halo, $nama');
}

jsonDecode mengubah string menjadi Map/List Dart. Tipe angka otomatis (int vs double), boolean, null, dan string nested.

Contoh kedua, JSON array:

dart
import 'dart:convert';

void main() {
  String jsonArr = '[{"nama":"Budi"},{"nama":"Ani"}]';

  List<dynamic> list = jsonDecode(jsonArr);
  for (var item in list) {
    print(item['nama']);
  }

  // Ke List<String> rapi
  var nama = list.map((e) => (e as Map)['nama'] as String).toList();
  print(nama); // [Budi, Ani]
}

Encode: Dart → JSON string

dart
import 'dart:convert';

void main() {
  var user = {
    'nama': 'Budi',
    'umur': 17,
    'hobi': ['membaca', 'ngoding'],
  };

  String json = jsonEncode(user);
  print(json); // {"nama":"Budi","umur":17,"hobi":["membaca","ngoding"]}

  // Pretty print untuk debugging
  var pretty = JsonEncoder.withIndent('  ').convert(user);
  print(pretty);
}

jsonEncode hanya menerima tipe yang bisa di-JSON-kan: Map, List, String, num, bool, null. Objek custom? Harus diubah ke Map dulu (lihat pola fromJson/toJson).

Pola fromJson/toJson pada class

dart
import 'dart:convert';

class Pengguna {
  String nama;
  int umur;

  Pengguna(this.nama, this.umur);

  // JSON -> objek
  factory Pengguna.dariJson(Map<String, dynamic> json) {
    return Pengguna(
      json['nama'] as String,
      json['umur'] as int,
    );
  }

  // objek -> JSON
  Map<String, dynamic> keJson() => {
        'nama': nama,
        'umur': umur,
      };
}

void main() {
  // Simulasi data dari API
  String responApi = '{"nama":"Ani","umur":20}';

  var user = Pengguna.dariJson(jsonDecode(responApi));
  print('Halo ${user.nama}, umur ${user.umur}');

  // Kirim kembali ke server
  String untukServer = jsonEncode(user.keJson());
  print(untukServer);
}

Pola dariJson/keJson adalah standar industri Flutter. Setiap model data memilikinya. (Package json_serializable bisa menggenerasinya otomatis untuk proyek besar.)

Kesalahan umum

1. Cast tanpa as

dart
void main() {
  var data = jsonDecode('{"umur": 17}');
  // String s = data['umur']; // ERROR: dynamic -> String
  int umur = data['umur'] as int; // BENAR
  print(umur);
}

Nilai dari JSON bertipe dynamic. Selalu cast (as) atau validasi sebelum dipakai sebagai tipe spesifik.

2. Kunci tidak ada → null

dart
void main() {
  var data = jsonDecode('{"nama": "Budi"}');
  // int umur = data['umur'] as int; // ERROR: null!
  int umur = (data['umur'] as int?) ?? 0; // BENAR
  print(umur);
}

API bisa berubah; kunci bisa hilang. Pakai cast nullable + ?? default.

3. jsonEncode objek custom langsung

dart
class A {
  String x = 'hi';
}

void main() {
  // print(jsonEncode(A())); // ERROR: tidak bisa di-encode!
  print(jsonEncode({'x': A().x})); // BENAR: ubah ke Map dulu
}

Kesimpulan

jsonDecode (string → Map/List), jsonEncode (Map/List → string), pola dariJson/keJson di class model. Selalu cast eksplisit dan tangani kunci yang mungkin hilang. Kuasai ini dan kamu siap bicara dengan API mana pun.

Catatan teknis: dart:convert juga berisi utf8, base64, dan LineSplitter. Untuk JSON besar, ada JsonDecoder streaming. Untuk model kompleks, pertimbangkan code generation via json_serializable.

Tantangan

Parser daftar pengguna

Diberi JSON string array pengguna (nama, umur). Decode, ubah jadi List<Pengguna> via Pengguna.dariJson, cetak nama yang umurnya >= 18, lalu encode kembali yang lolos ke JSON.

text
import 'dart:convert';

class Pengguna {
  String nama;
  int umur;
  Pengguna(this.nama, this.umur);
  factory Pengguna.dariJson(Map<String, dynamic> j) =>
      Pengguna(j['nama'] as String, j['umur'] as int);
  Map<String, dynamic> keJson() => {'nama': nama, 'umur': umur};
}

void main() {
  String jsonStr = '[{"nama":"Budi","umur":17},{"nama":"Ani","umur":20}]';
  // TODO: decode -> List<Pengguna> -> filter >= 18 -> encode
}