Jika kamu pernah bekerja dengan microservices, pasti sudah tidak asing lagi dengan Protobuf sebagai serialization format. Dukungan Protobuf terhadap message exchange yang cepat sekaligus schema-typed menjadi alasan utama format ini digandrungi di ekosistem Go dan berbagai bahasa lainnya. Namun, realita di lapangan sering kali menuntut interoperabilitas service-service berbasis JSON ― baik untuk logging, REST API, ataupun debugging. Maka di sinilah fitur marshal dan unmarshal JSON pada Protobuf menjadi sangat penting.
Pada artikel kali ini, kita akan membahas secara komprehensif proses Marshal dan Unmarshal JSON pada Protobuf di Go. Kita akan mengeksplorasi implementasi, simulasi, hingga potensi pitfall yang mesti diwaspadai.
Ringkasan Istilah
Istilah | Penjelasan |
---|---|
Marshal | Mengkonversi (encode) data struktur ke format lain (misal: Protobuf ke JSON) |
Unmarshal | Mengkonversi (decode) data dari format lain ke struktur (misal: JSON ke Protobuf struct) |
Protobuf | Format serialisasi biner yang schema-typed dari Google |
JSON | Format data berbasis teks yang mudah dibaca manusia |
Kenapa Protobuf JSON Marshal/Unmarshal Diperlukan?
Walau Protobuf mengandalkan encoding binary, namun berbagai use-case meminta format JSON. Beberapa situasi seperti:
- Logging berbasis JSON untuk konsistensi stack.
- REST API yang secara kontrak memerlukan body berformat JSON.
- Debugging manual terhadap payload.
- Backward compatibility dengan sistem warisan yang masih pakai JSON.
Diagram Alur Proses
Mari kita ilustrasikan alurnya memakai diagram flowchart sederhana.
flowchart LR A[Struct Protobuf] --Marshal--> B[JSON] B --Unmarshal--> C[Struct Protobuf]
Alur di atas memperjelas bahwa ada proses dua arah dari Protobuf ke JSON (Marshal
) dan sebaliknya (Unmarshal
).
Setup Protobuf dan Go
Sebelum masuk ke kode, pastikan punya setup berikut:
- Golang (1.18+)
- protoc
- protobuf-go plugin:
google.golang.org/protobuf
Contoh .proto
file sederhana:
syntax = "proto3";
package article;
message User {
int32 id = 1;
string name = 2;
bool is_active = 3;
}
Generate Go file:
protoc --go_out=. user.proto
Implementasi Marshal dan Unmarshal
1. Marshal ke JSON
google.golang.org/protobuf/encoding/protojson
menyediakan utility untuk Marshal dan Unmarshal.
Contoh kode:
package main
import (
"fmt"
"log"
"google.golang.org/protobuf/encoding/protojson"
pb "path/to/generated/package/article"
)
func main() {
user := &pb.User{
Id: 50,
Name: "Sophia",
IsActive: true,
}
// Marshal ke JSON
data, err := protojson.Marshal(user)
if err != nil {
log.Fatalf("marshal error: %v", err)
}
fmt.Println(string(data))
}
Output:
{"id":50,"name":"Sophia","isActive":true}
Pro Tip:
Output secara default hanya membawa field yang diisi. Untuk output yang lebih readable, gunakan:
marshaller := protojson.MarshalOptions{
Multiline: true,
EmitUnpopulated: true,
Indent: " ",
}
jsonData, _ := marshaller.Marshal(user)
fmt.Println(string(jsonData))
2. Unmarshal dari JSON ke Protobuf
Mari simulasikan proses sebaliknya: JSON ke struct Protobuf.
jsonStr := `{"id":90,"name":"Aston","isActive":false}`
var user pb.User
err := protojson.Unmarshal([]byte(jsonStr), &user)
if err != nil {
log.Fatalf("unmarshal error: %v", err)
}
fmt.Printf("Unmarshalled: %#v\n", user)
Output:
Unmarshalled: article.User{Id:90, Name:"Aston", IsActive:false, ...}
Simulasi: Menangani Field Kosong
Berikut adalah tabel mapping perilaku marshal/unmarshal terkait field kosong pada Protobuf dan JSON.
Field Protobuf | Nilai | Setelah Marshal ke JSON | Uraian |
---|---|---|---|
id (int32) | 0 | Hilang/Tampil (1) | Default hilang, atau tampil jika EmitUnpopulated |
name (string) | "" | Hilang/Tampil (1) | Sama |
is_active (bool) | false | Hilang/Tampil (1) | Sama |
(1) Mengatur EmitUnpopulated: true
pada opsi Marshal membuat JSON mencantumkan default value.
Contoh Perbandingan:
user := &pb.User{} // semuanya default
defaultOutput, _ := protojson.Marshal(user)
withOpt := protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(user)
fmt.Println("Biasa:", string(defaultOutput))
fmt.Println("EmitUnpopulated:", string(withOpt))
Output:
Biasa: {}
EmitUnpopulated: {"id":0,"name":"","isActive":false}
Pitfall dan Best Practices
1. Ekspose Internal Field
- Field Protobuf tidak semua langsung tampil di JSON, misal field oneof atau map.
2. Nilai Default
- Nilai default di Protobuf (
0
,false
,""
) tidak otomatis muncul di JSON tanpa setEmitUnpopulated
.
3. Kompatibilitas
- JSON Protobuf bisa beda dengan JSON tag struct Go biasa. Misal, field-casing dan enum bisa beda penulisan.
4. Array dan Repeated Field
- Empty list tetap muncul sebagai
[]
jikaEmitUnpopulated: true
.
5. Oneof / Any
- Pemrosesan oneof dan type
Any
membutuhkan perhatian khusus. Kadang-kadang lebih baik membuat handler custom.
Skenario Lanjutan: Interop Service
Misalkan salah satu service mengirim JSON ke service lain, lalu dilakukan unmarshal ke Protobuf.
sequenceDiagram participant Client participant ServiceA participant ServiceB Client->>ServiceA: Kirim JSON Payload ServiceA->>ServiceA: Unmarshal ke Protobuf Struct ServiceA->>ServiceB: Marshal ke Binary Protobuf ServiceB->>ServiceB: Unmarshal dari Binary
Kesimpulan
Marshal dan Unmarshal antara Protobuf dan JSON di Go sangat mudah dengan bantuan protojson
. Namun, seperti layaknya engineer yang teliti, penting untuk memahami default behavior, pengaturan option, serta antagonis kecil seperti field kosong atau distorsi serialisasi.
Bekerjalah dengan schema-first mindset dan pastikan output telah tervalidasi dengan konsumen dari masing-masing format. Pengalaman akan mengajarkan edge case yang tidak selalu ter-cover oleh tutorial standar.
Jika kamu ingin berdiskusi lebih jauh terkait schema evolution dan serialisasi di sistem enterprise, jangan ragu untuk berdiskusi di kolom komentar. Selamat berkarya dan happy marshalling! 🚀
Referensi
27 Menulis Skema Mutation di GraphQL
Artikel Terhangat
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
26 Apa Itu Mutation dan Kapan Digunakan?
07 Jul 2025
48 Custom Options di Protobuf
07 Jul 2025

51. Menggunakan TLS di gRPC Server

50 Protobuf JSON Marshal dan Unmarshal

27 Menulis Skema Mutation di GraphQL

49 Serialisasi dan Deserialisasi Manual

26 Apa Itu Mutation dan Kapan Digunakan?
