Episode ini membahas pengelolaan data di Rust: serialisasi dan deserialisasi dengan serde untuk format JSON dan TOML, I/O file dan network stream, async I/O dengan tokio, serta integrasi database dengan sqlx, diesel, atau sea-orm.

Aplikasi modern jarang berisi data statis di dalam kode: kalian membaca konfigurasi, menyimpan data, memanggil API, dan menulis log. Semuanya melibatkan serialisasi — mengubah data menjadi format yang bisa dikirim dan disimpan — serta I/O dengan file, jaringan, dan database.
Episode 8 membedah ketiganya: serde sebagai standar serialisasi de facto, file dan async I/O dengan tokio, serta integrasi database dengan sqlx. Setelah episode ini, kalian bisa membangun lapisan data yang nyata.
serde adalah framework serialisasi dengan ekosistem format: JSON, TOML, YAML, dan banyak lagi. Semua dipicu oleh derive macro Serialize dan Deserialize.
cargo add serde --features derive
cargo add serde_jsoncargo add serde --features derive mengaktifkan macro. serde_json menyediakan format JSON. Struktur data cukup diberi anotasi derive:
cat > src/main.rs <<'EOF'
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Server {
nama: String,
port: u16,
aktif: bool,
}
fn main() {
let server = Server {
nama: String::from("api"),
port: 8080,
aktif: true,
};
let json = serde_json::to_string(&server).unwrap();
println!("{}", json);
let kembali: Server = serde_json::from_str(&json).unwrap();
println!("{}:{}", kembali.nama, kembali.port);
}
EOF
cargo runserde_json::to_string mengubah struct menjadi JSON, dan from_str membaliknya. Karena validasi dilakukan lewat tipe, data yang tidak cocok ditolak saat deserialisasi — bukan nanti saat dipakai.
Prinsip yang sama berlaku untuk format lain. toml::from_str mengurai teks TOML ke struct dengan pola derive yang sama:
cat > src/main.rs <<'EOF'
use serde::Deserialize;
#[derive(Deserialize)]
struct Config {
host: String,
port: u16,
}
fn main() {
let sumber = r#"
host = "127.0.0.1"
port = 5432
"#;
let config: Config = toml::from_str(sumber).unwrap();
println!("{}:{}", config.host, config.port);
}
EOF
cargo run#[derive(Deserialize)] yang sama berlaku untuk JSON, TOML, dan YAML — itulah kekuatan serde: sekali definisi tipe, banyak format.
Standard library menyediakan I/O file sinkron di std::fs:
cat > src/main.rs <<'EOF'
use std::fs;
fn main() {
fs::write("catatan.txt", "belajar rust\n").unwrap();
let isi = fs::read_to_string("catatan.txt").unwrap();
println!("{}", isi.trim());
fs::remove_file("catatan.txt").unwrap();
}
EOF
cargo runfs::write, fs::read_to_string, dan fs::remove_file menangani kasus umum. Untuk kebutuhan lanjutan, File, Read, dan Write memberi kontrol penuh. Semua mengembalikan Result sehingga error bisa dipropagasi dengan ?.
Operasi I/O lambat seharusnya tidak memblokir thread. tokio adalah runtime async paling populer: ia menyediakan executor dan jenis I/O non-blocking.
cat > src/main.rs <<'EOF'
use tokio::fs;
#[tokio::main]
async fn main() {
let isi = fs::read_to_string("Cargo.toml").await.unwrap();
println!("baris: {}", isi.lines().count());
}
EOF
cargo run#[tokio::main] mengubah main menjadi async entry point. .await menunda eksekusi tanpa memblokir thread — thread yang sama bisa melayani banyak operasi bersamaan. Pola ini akan dipakai penuh di episode 10 dan 12.
sqlx memeriksa query SQL saat kompilasi, sehingga typo di SQL tertangkap sebelum runtime:
cat > src/main.rs <<'EOF'
use anyhow::Result;
use sqlx::postgres::PgPoolOptions;
#[derive(sqlx::FromRow)]
struct Pengguna {
id: i32,
nama: String,
}
#[tokio::main]
async fn main() -> Result<()> {
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgres://user:pass@localhost/db")
.await?;
let pengguna: Vec<Pengguna> = sqlx::query_as(
"SELECT id, nama FROM pengguna WHERE aktif = true",
)
.fetch_all(&pool)
.await?;
println!("total: {}", pengguna.len());
Ok(())
}
EOF
cargo runPgPoolOptions membuat connection pool yang dibagi antar task. query_as memetakan baris ke struct Pengguna. Dengan DATABASE_URL dan feature postgres, macro query! bisa memvalidasi query terhadap skema database secara langsung saat kompilasi.
Alternatif lain: diesel adalah ORM sinkron yang aman dengan tipe, sedangkan sea-orm adalah ORM async di atas sqlx. Pilihannya: sqlx untuk kontrol penuh atas SQL, diesel untuk ORM matang dengan dukungan migrasi kuat, sea-orm untuk ekosistem async dan model aktif. Semua mendukung migrasi skema — tema yang kita lanjutkan di episode 9.
Inti yang harus dibawa pulang:
Serialize dan Deserialize adalah standar serialisasi.std::fs untuk I/O sinkron; tokio untuk I/O async non-blocking.Di episode 9 selanjutnya kita akan membahas schema evolution, config, dan environment — konfigurasi aplikasi dengan config, dotenv, atau figment, versioning data dan compatibility tipe, serta praktik separation config per environment dev, staging, dan production.