Serialisasi dan deserialisasi merupakan proses fundamental dalam dunia pengembangan perangkat lunak modern. Keduanya menjadi tulang punggung dalam pertukaran data lintas sistem, penyimpanan objek kompleks ke dalam berkas, hingga komunikasi antara layanan menggunakan protokol tertentu. Akan tetapi, sering kali alat atau pustaka otomatis seperti JSON, Protocol Buffer, atau YAML yang kita gunakan “menyembunyikan” kompleksitas ini. Tapi apa yang terjadi ketika kita harus melakukan serialisasi dan deserialisasi secara manual?
Artikel ini membahas serialisasi dan deserialisasi manual—upaya eksplisit mengubah struktur data ke dalam format tertentu (dan sebaliknya) tanpa bergantung pada pustaka khusus. Kita akan menelusuri alasan mengapa teknik ini penting, tantangan yang muncul, beserta contoh kode di Python dan Java beserta simulasi prosesnya.
Apa itu Serialisasi dan Deserialisasi?
Secara sederhana:
- Serialisasi adalah proses mengubah objek/struktur data menjadi format yang dapat disimpan atau dikirim (string, byte-stream, dsb).
- Deserialisasi adalah proses kebalikannya: mengubah representasi data hasil serialisasi menjadi objek/struktur data kembali.
Jika pernah menggunakan:
import json
json.dumps({'name': 'Budi', 'age': 30})
Anda telah memakai serialisasi otomatis.
Mengapa Serialisasi Manual?
- Kontrol Penuh: Kadang-kadang format output atau input harus memenuhi standar yang sangat spesifik (misal: format ID yang fixed-length, penamaan field tak konvensional).
- Ukuran Data: SERIALIZATION library standar bisa menghasilkan output besar; manual bisa dirancang lebih minimalis.
- Kebutuhan Performa: Untuk data bervolume besar dan komunikasi dengan waktu kritis (low-latency), serialisasi manual memungkinkan optimasi tingkat rendah.
- Keamanan: Serialisasi otomatis kadang membuka celah injection/deserialization attack.
Serialisasi Manual: Studi Kasus
Mari kita gunakan sebuah contoh sederhana—serialisasi objek pengguna (user) dengan atribut: id: int
, username: string
, active: bool
.
1. Spesifikasi Format Serialisasi
Kita tentukan format khusus:
id
fixed 4 digit, leading zero (misal 42 => “0042”)username
max 8 karakter, di-pad dengan spasi jika kurang (misal “budi” => “budi “)active
dengan1
(True) atau0
(False)
Contoh hasil serialisasi, untuk user id=7, username=“lina”, active=True:
0007lina 1
2. Kode Serialisasi Manual
a) Python Implementation
class User:
def __init__(self, id, username, active):
self.id = id
self.username = username
self.active = active
def serialize(self):
id_str = str(self.id).zfill(4)
username_str = self.username.ljust(8)
active_str = '1' if self.active else '0'
return f"{id_str}{username_str}{active_str}"
@staticmethod
def deserialize(serialized_str):
id = int(serialized_str[:4])
username = serialized_str[4:12].rstrip()
active = serialized_str[12] == '1'
return User(id, username, active)
# Simulasi proses
u = User(42, "neo", True)
ser = u.serialize()
print('Serialized:', ser) # Output: "0042neo 1"
u2 = User.deserialize(ser)
print('Deserialized:', (u2.id, u2.username, u2.active)) # Output: (42, 'neo', True)
b) Java Implementation
class User {
int id;
String username;
boolean active;
User(int id, String username, boolean active) {
this.id = id;
this.username = username;
this.active = active;
}
String serialize() {
return String.format("%04d%-8s%d", id, username, active ? 1 : 0);
}
static User deserialize(String str) {
int id = Integer.parseInt(str.substring(0, 4));
String username = str.substring(4, 12).trim();
boolean active = str.charAt(12) == '1';
return new User(id, username, active);
}
}
c) Go Implementation
package main
import (
"fmt"
"strconv"
"strings"
)
type User struct {
ID int
Username string
Active bool
}
// Serialize mengubah User menjadi string format: 4 digit ID, 8 karakter username (padding), 1 digit active (0/1)
func (u User) Serialize() string {
activeInt := 0
if u.Active {
activeInt = 1
}
return fmt.Sprintf("%04d%-8s%d", u.ID, u.Username, activeInt)
}
// Deserialize mengubah string ke User struct
func Deserialize(data string) (User, error) {
if len(data) < 13 {
return User{}, fmt.Errorf("data too short")
}
id, err := strconv.Atoi(data[0:4])
if err != nil {
return User{}, fmt.Errorf("invalid ID: %w", err)
}
username := strings.TrimSpace(data[4:12])
active := data[12] == '1'
return User{
ID: id,
Username: username,
Active: active,
}, nil
}
func main() {
u := User{ID: 42, Username: "ihsan", Active: true}
serialized := u.Serialize()
fmt.Println("Serialized:", serialized)
parsed, err := Deserialize(serialized)
if err != nil {
panic(err)
}
fmt.Printf("Deserialized: %+v\n", parsed)
}
Output:
Serialized: 0042ihsan 1
Deserialized: {ID:42 Username:ihsan Active:true}
Catatan:
- Username dipastikan selalu panjang 8 karakter, sesuai format Java-nya.
- Fungsi
Deserialize
meng-handle input dengan validasi panjang minimal. - Struct mirip dengan pendekatan fixed-width serialization.
Diagram Alur Serialisasi dan Deserialisasi Manual
flowchart LR A[Objek User] -- serialize() --> B[Serialized String] B -- deserialize() --> A
Gambaran di atas memperjelas: serialisasi mengubah objek menjadi string yang disimpan, dikirim, atau diproses lebih lanjut; deserialisasi mengembalikannya ke bentuk semula.
Simulasi: Serialisasi Manual vs Otomatis
Fitur | Manual | Otomatis (JSON) |
---|---|---|
Kontrol format | Penuh | Terbatas |
Evolusi skema | Risiko human error | Lebih terjamin |
Error Handling | Tanggung jawab dev | Lib menyediakan |
Speed | Potensi tinggi | Umumnya cukup |
Keamanan | Wajib teliti | Relatif aman* |
Potensi Risiko dan Perhatian
- Human Error: Kesalahan offset (misal index slicing salah) akan menyebabkan data korup atau salah interpretasi.
- Compatibility: Jika format berubah, seluruh proses serialisasi/deserialisasi harus diperbarui konsisten.
- Scalability: Untuk objek nested/kompleks, kode manual cepat menjadi sulit dirawat.
- Validasi: Tidak ada validasi otomatis kecuali kita membangunnya sendiri (misal username harus 8 karakter atau kurang).
Best Practice Serialisasi Manual
- Definisikan Spesifikasi Format secara jelas dan dokumentasikan.
- Sertakan unit test untuk semua edge case (angka dengan panjang berbeda, nama pendek dan panjang, flag boolean).
- Pisahkan kode serialisasi dari logika bisnis utama untuk memudahkan refactoring.
- Gunakan exception handling agar error mudah ditemukan (misal incomplete string).
- Jika struktur berkembang (misal: bertambah field), buat versioning dalam string serialisasi.
Kesimpulan
Serialisasi dan deserialisasi manual tetap menjadi senjata penting dalam toolkit seorang engineer, meski di era frameworks serba otomatis. Ia memastikan adanya fleksibilitas dan kontrol maksimal tatkala kebutuhan bisnis atau sistem mendorong pada standar spesifik dan performa optimal. Namun, semestinya disertai disiplin dokumentasi dan testing yang baik agar tidak menjadi sumber masalah laten di masa depan.
Jadi, di tengah kebebasan dan kekuatan serialisasi otomatis, pahami kapan harus “turun tangan” dan melakukan serialisasi secara manual. Kerap kali di situlah seni sejati berprogram tampil: mengubah struktur menjadi kode, dan kode menjadi struktur, secara presisi layaknya seorang tukang jam klasik.
*Catatan: Untuk konteks keamanan, baik manual maupun otomatis tetap memerlukan pengamanan dari serangan deserialization exploits pada data tak dipercaya.
Referensi:
26 Apa Itu Mutation dan Kapan Digunakan?
27 Menulis Skema Mutation di GraphQL
Artikel Terhangat
30 Validasi Input di Mutation graphql-go
07 Jul 2025
51. Menggunakan TLS di gRPC Server
07 Jul 2025
50 Protobuf JSON Marshal dan Unmarshal
07 Jul 2025
27 Menulis Skema Mutation di GraphQL
07 Jul 2025
49 Serialisasi dan Deserialisasi Manual
07 Jul 2025

30 Validasi Input di Mutation graphql-go

51. Menggunakan TLS di gRPC Server

50 Protobuf JSON Marshal dan Unmarshal

27 Menulis Skema Mutation di GraphQL
