Skip to content
Kembali ke Blog
Tutorial

Masalah Norway YAML dan Perbedaan JSON-YAML untuk Engineer

Mengapa YAML membaca "no" sebagai false. Gangguan produksi K8s akibat pengutipan string. Pilihan JSON vs YAML, aturan indentasi & konversi manifest K8s.

14 menit baca

Masalah Norway YAML dan Perbedaan JSON ↔ YAML yang Harus Diketahui Engineer

Itu adalah deployment Helm yang rutin. Tim telah menghabiskan dua hari menyempurnakan file values.yaml untuk rollout multi-region. Chart tersebut men-template sebuah Kubernetes ConfigMap dengan metadata locale — termasuk kode negara untuk pusat data Norwegia mereka. Seseorang mengetik country: NO dan meng-commit-nya. Pipeline CI berjalan hijau. Deployment berjalan.

Kemudian alert masuk.

ConfigMap berisi country: false alih-alih country: "NO". Setiap layanan hilir yang membaca field country mendapatkan boolean alih-alih string. Perbandingan string gagal. Logika routing jatuh ke default. Traffic yang seharusnya tetap di Norwegia malah diproses oleh endpoint regional yang salah.

Akar masalahnya adalah satu string tanpa kutip dalam file YAML. YAML 1.1 — versi yang digunakan hampir semua tooling Kubernetes — memperlakukan NO sebagai boolean false. Ia memperlakukan YES, ON, OFF, Y, N, no, yes, on, off, y, n, dan selusin varian lainnya dengan cara yang sama. Tanpa peringatan. Tanpa error. Diam-diam salah.

JSON tidak memiliki masalah ini. {"country": "NO"} selalu berupa string. Konversi tipe implisit YAML adalah kenyamanan terbesar sekaligus jebakan paling berbahaya.

Panduan ini mencakup gambaran lengkap: mengapa masalah Norway ada, apa yang berubah di YAML 1.2 (dan mengapa sebagian besar tooling mengabaikannya), cara menulis strategi pengutipan yang benar, aturan indentasi yang sering membingungkan pemula, jebakan presisi angka, dan empat skenario konversi dunia nyata mulai dari manifest Kubernetes hingga Terraform plan. Ketika Anda perlu secara aman meratakan nilai JSON ke YAML tanpa jebakan ini, konverter JSON ke YAML kami secara otomatis mengutip string yang bermasalah dengan Norway.

JSON vs YAML — Kapan Menggunakan Yang Mana

Sebelum menyelami masalah Norway, penting untuk memahami apa yang sebenarnya dioptimalkan oleh masing-masing format. Keduanya tidak dapat dipertukarkan — masing-masing memiliki pusat desain yang menjadikannya pilihan lebih baik dalam konteks tertentu.

DimensiJSONYAML
SintaksKetat — kurung kurawal, kutipan, koma wajibFleksibel — berbasis indentasi, tanda baca minimal
Sistem tipeEksplisit: string, angka, boolean, null, array, objekImplisit — YAML 1.1 menyimpulkan tipe dari bentuk nilai
Keterbacaan manusiaRamah developer, dapat diverifikasi mesinRamah manusia, mudah diedit tangan
Kebutuhan kutipanString selalu dikutipSebagian besar scalar dapat tanpa kutipan (sumber masalah Norway)
KomentarTidak didukungDidukung dengan #
Penggunaan utamaAPI, pertukaran data, sistem konfigurasi modernKubernetes, Docker Compose, Ansible, pipeline CI
Parse mengejutkanTidak ada — parsing ketatYa — Norway, oktal, timestamp
Penegakan skemaEkosistem JSON SchemaYAML Schema (tooling lebih sedikit)

JSON menang ketika data Anda melintasi batas sistem — REST API, antrian pesan, serialisasi database. Mesin mem-parsing-nya, mesin menghasilkannya, dan sintaks yang ketat membuat validasi mudah. Gunakan JSON Formatter untuk memvalidasi struktur sebelum mengirim.

YAML menang ketika manusia adalah penulis utama. Manifest Kubernetes, workflow GitHub Actions, chart Helm, playbook Ansible — ini adalah file yang dibaca dan diedit developer puluhan kali. Tanda baca yang berkurang dan dukungan untuk komentar membuatnya benar-benar lebih mudah dipelihara daripada padanan JSON-nya.

Masalah muncul di batas: ketika sebuah alat menghasilkan JSON (seperti kubectl get deploy -o json atau terraform show -json) dan manusia perlu mengontrol versi atau mengedit hasilnya sebagai YAML. Konversi itulah tempat masalah Norway berada. Konverter YAML ke JSON kami menangani arah sebaliknya ketika Anda perlu kembali.

Masalah Norway — Pembahasan Mendalam

Masalah Norway bukan bug. Ini adalah fitur spesifikasi YAML 1.1 yang berperilaku persis seperti yang dirancang. Memahami mengapa ia dirancang demikian — dan mengapa begitu banyak sistem masih mengimplementasikan 1.1 — adalah kunci untuk menghindarinya.

Mengapa “no”, “yes”, “on”, “off”, “y”, “n” Diparsing Salah

Spesifikasi YAML 1.1 mendefinisikan tipe boolean yang luas yang dimaksudkan untuk ramah manusia. Ia mengenali semua hal berikut sebagai true atau false:

True: y, Y, yes, Yes, YES, true, True, TRUE, on, On, ON

False: n, N, no, No, NO, false, False, FALSE, off, Off, OFF

Niatnya baik: file konfigurasi sering menggunakan yes/no alih-alih true/false dalam bahasa Inggris, dan YAML ingin mendukung cara alami orang menulis konfigurasi. Masalahnya adalah yes, no, on, off, y, dan n juga merupakan nilai string yang sah yang memiliki arti yang sama sekali berbeda di sebagian besar aplikasi.

Berikut ketidaksesuaian dalam YAML konkret:

# YAML 1.1 (yang diimplementasikan sebagian besar parser)
country: NO        # diparsing sebagai: country: false   ← BAHAYA
enabled: yes       # diparsing sebagai: enabled: true
restart: off       # diparsing sebagai: restart: false
language: y        # diparsing sebagai: language: true
shell: n           # diparsing sebagai: shell: false

# Benar — tanda kutip string eksplisit mengesampingkan inferensi tipe
country: "NO"      # diparsing sebagai: country: "NO"    ← aman
enabled: "yes"     # diparsing sebagai: enabled: "yes"
restart: "off"     # diparsing sebagai: restart: "off"
language: "y"      # diparsing sebagai: language: "y"
shell: "n"         # diparsing sebagai: shell: "n"

Dan perbandingan JSON:

{"country": "NO"}

Dalam JSON, NO di dalam kutipan selalu dan tanpa syarat merupakan string. Tidak ada inferensi tipe implisit. Ketegasan yang membuat JSON terasa verbose juga yang membuatnya aman.

Di luar konversi boolean, YAML 1.1 juga secara implisit mengonversi:

  • 123e4 → angka 1230000 (notasi ilmiah)
  • 0x1A → angka 26 (heksadesimal)
  • 0755 → angka 493 (oktal — ini merusak string izin file Unix)
  • 2024-05-04 → objek tanggal di banyak parser (bukan hanya string)
  • 1_000_000 → angka 1000000 (pemisah garis bawah)

Masalah Norway sebenarnya hanyalah anggota paling terkenal dari seluruh keluarga konversi tipe implisit YAML.

YAML 1.1 vs 1.2 — Apa yang Berubah

YAML 1.2 diterbitkan pada 2009 — empat tahun setelah YAML 1.1. Tujuan utamanya adalah membawa YAML ke keselarasan ketat dengan JSON (karena JSON sebenarnya merupakan subset YAML 1.2 yang valid) dan mengurangi konversi tipe implisit yang mengejutkan.

Dalam YAML 1.2:

  • Boolean dipersempit menjadi tepat true dan false (peka huruf besar-kecil). Hanya itu. yes, no, on, off adalah string biasa.
  • Literal oktal memerlukan prefiks 0o (0o755) — bentuk lama 0755 adalah string.
  • Timestamp tidak diparsing secara implisit — 2024-05-04 tetap menjadi string kecuali Anda menandainya secara eksplisit.
  • Spesifikasi itu sendiri adalah superset JSON, artinya setiap dokumen JSON yang valid adalah YAML 1.2 yang valid.

Di atas kertas, YAML 1.2 sepenuhnya menyelesaikan masalah Norway. Dalam praktiknya, ekosistem hampir tidak bergerak.

LibrarySpesifikasi defaultRisiko Norway
PyYAML (Python)YAML 1.1Ya — yaml.safe_load masih mem-parsing NO sebagai False
ruamel.yaml (Python)YAML 1.2 (opsional)Dapat dikonfigurasi — lebih aman secara default
js-yaml (Node.js)YAML 1.1Ya di versi lama; versi baru memiliki opsi FAILSAFE_SCHEMA
eemeli/yaml (Node.js)YAML 1.2Tidak — 1.2 secara default, atau dapat dipilih secara eksplisit
gopkg.in/yaml.v2 (Go)YAML 1.1Ya
gopkg.in/yaml.v3 (Go)YAML 1.2Jauh lebih aman
Kubernetes / HelmYAML 1.1 (via Go yaml.v2)Ya — historis, sangat sulit dimigrasikan
AnsibleYAML 1.1 (via PyYAML)Ya

Alasan migrasi lambat adalah kompatibilitas mundur. Sistem yang telah mengandalkan yes/no diparsing sebagai boolean selama satu dekade tidak dapat secara diam-diam mengubah perilaku itu tanpa merusak konfigurasi yang ada. Kubernetes khususnya memiliki basis instalasi yang sangat besar di mana mengubah semantik parsing YAML akan menjadi perubahan breaking di seluruh cluster.

Kesimpulan praktis: asumsikan semantik YAML 1.1 di alat mana pun yang tidak Anda konfigurasi secara eksplisit. Selalu kutip string yang bisa salah dibaca sebagai boolean, timestamp, atau angka.

Bagaimana Sistem Produksi Terdampak

Kode negara Norway adalah contoh yang paling sering dikutip karena tidak intuitif — NO terlihat seperti singkatan yang jelas, bukan boolean. Tetapi pola ini berulang di banyak skenario dunia nyata:

Kode bandara IATA. Bandara Norwegia Harstad/Narvik memiliki kode EVE. Aman. Oslo Gardermoen adalah OSL. Juga aman. Tetapi aplikasi mana pun yang menggunakan YAML untuk menyimpan kode bandara regional hanya satu kode rute no dari boolean false di produksi.

Nama variabel environment. ON adalah nilai variabel environment yang sah yang berarti “diaktifkan” di beberapa sistem lama. OFF adalah padanannya. Memigrasikan konfigurasi dari shell script ke YAML tanpa mengutip nilai-nilai ini memperkenalkan konversi tipe diam-diam.

Field pengguna email. Pengguna yang nama depan atau username-nya adalah n, y, atau salah satu kata pemicu akan diserialisasi secara tidak benar jika aplikasi membuang YAML tanpa pengutipan yang tepat. Ini sangat berbahaya karena hanya gagal untuk sebagian kecil pengguna.

Kebijakan restart Docker Compose. Nilai field restart_policy yaitu "no" berarti “jangan restart.” Jika kutipannya hilang dalam round-trip YAML, nilainya menjadi false, dan Docker Compose mungkin mengartikannya sebagai “tidak ada kebijakan restart yang ditentukan” atau melempar error validasi — bagaimanapun, perilaku restart container salah.

Field shell: GitHub Actions. Nilai shell yang valid adalah bash, pwsh, python, sh, cmd, powershell. Tidak ada yang merupakan kata Norway. Tetapi seseorang yang mengetik shell: yes atau shell: on sebagai placeholder selama pengeditan draft mungkin terkejut ketika YAML mengubahnya menjadi boolean sebelum validator bahkan melihatnya.

Perbaikan di semua kasus adalah sama: kutip string yang secara semantis merupakan string, terlepas dari apakah manusia akan mengenalinya sebagai kata kunci. Konverter JSON ke YAML kami menerapkan ini secara otomatis — nilai mana pun dalam daftar kata Norway dikutip di output.

Strategi Pengutipan String

Setelah Anda memahami mengapa kata Norway tidak cocok, solusinya adalah memilih strategi pengutipan yang tepat untuk kasus penggunaan Anda. YAML mendukung tiga mode, masing-masing dengan tradeoff yang berbeda.

Auto vs Double vs Single

Pengutipan Auto (direkomendasikan untuk sebagian besar konversi) membiarkan library memutuskan kapan kutipan diperlukan. Nilai yang akan salah dibaca tanpa kutipan — kata Norway, angka, timestamp, string yang terlihat seperti sintaks YAML — dikutip secara otomatis. Semua yang lain tetap sebagai scalar biasa. Ini menghasilkan output yang paling mudah dibaca sekaligus tetap aman.

# Output mode Auto
name: Alice          # biasa — tidak ambigu
country: "NO"        # dikutip — kata Norway
age: 30              # biasa — angka tidak ambigu
created: "2024-05-04" # dikutip — jika tidak akan diparsing sebagai tanggal
port: "8080"         # tergantung library — beberapa mengutip string yang terlihat numerik

String tanda kutip ganda membungkus semua nilai string dalam tanda kutip ganda. Ini eksplisit dan dapat diaudit — pembaca mana pun dapat melihat bahwa semua nilai ini adalah string tanpa perlu memikirkan spesifikasinya. Tradeoffnya adalah verbositas dan berkurangnya keterbacaan manusia, terutama untuk konfigurasi yang sangat bertingkat.

# Mode tanda kutip ganda
name: "Alice"
country: "NO"
replicas: "3"         # bahkan angka menjadi string — mungkin menyebabkan error skema

Hati-hati: jika skema target Anda mengharapkan angka dan Anda menserialisasinya sebagai string yang dikutip, parser YAML akan mengetiknya dengan benar sebagai string, tetapi Kubernetes atau konsumen ketat lainnya mungkin menolak field tersebut sebagai tipe yang salah.

String tanda kutip tunggal adalah fitur khusus YAML — JSON tidak memiliki sintaks tanda kutip tunggal. Tanda kutip tunggal bersifat literal: tidak ada urutan escape di dalamnya. Satu-satunya kasus khusus adalah tanda kutip tunggal di dalam string tanda kutip tunggal harus digandakan (''). Tanda kutip tunggal ideal untuk string yang mengandung backslash atau karakter khusus yang perlu di-escape dalam tanda kutip ganda.

# Mode tanda kutip tunggal
pattern: 'C:\Users\alice\Documents'  # tidak perlu escape
regex: '\d+\.\d+'                    # backslash literal

Untuk konversi JSON-ke-YAML yang dimaksudkan untuk round-trip kembali ke JSON, lebih suka mode Auto atau Double. String tanda kutip tunggal memperkenalkan sintaks khusus YAML yang memerlukan parser yang mengenali YAML dalam perjalanan kembali.

Block Scalar (| dan >)

Sintaks block scalar YAML benar-benar berguna untuk string multi-baris — sesuatu yang ditangani JSON dengan canggung menggunakan urutan escape \n.

Block scalar literal | mempertahankan newline secara tepat:

# Block literal — newline dipertahankan
script: |
  #!/bin/bash
  set -euo pipefail
  echo "Starting deployment"
  kubectl apply -f manifest.yaml

# Representasi JSON yang setara (tidak terbaca)
# {"script": "#!/bin/bash\nset -euo pipefail\necho \"Starting deployment\"\nkubectl apply -f manifest.yaml\n"}

Block scalar folded > menggabungkan baris dengan spasi, mengubah setiap newline menjadi spasi (kecuali baris kosong, yang menjadi newline):

# Block folded — newline menjadi spasi
description: >
  Layanan ini menangani autentikasi
  untuk seluruh platform. Ia mendukung
  OAuth2, SAML, dan autentikasi API key.

# Hasil: "Layanan ini menangani autentikasi untuk seluruh platform. Ia mendukung OAuth2, SAML, dan autentikasi API key.\n"

Block scalar bersinar untuk menyematkan sertifikat TLS, shell script multi-baris, atau query SQL dalam konfigurasi YAML — skenario di mana padanan JSON-nya adalah one-liner panjang yang di-escape yang tidak dapat dibaca manusia mana pun.

Saat mengonversi dari JSON ke YAML, sebagian besar konverter (termasuk milik kami) menggunakan mode Auto dan merepresentasikan string multi-baris dengan block scalar hanya ketika mendeteksi newline yang disematkan. String satu baris mendapatkan flow scalar (dikutip atau biasa). Gunakan konverter JSON ke YAML kami untuk melihat output sebelum meng-commit-nya ke manifest.

Indentasi — 2 vs 4 Spasi, Tab Dilarang

Aturan indentasi YAML lebih ketat dari yang terlihat. Spesifikasi memiliki satu aturan absolut dan satu konvensi yang bervariasi menurut ekosistem.

Aturan absolut: tab dilarang. Setiap level indentasi harus menggunakan spasi. Karakter tab dalam file YAML adalah error parse di sebagian besar parser:

# SALAH — tab menyebabkan error parse
apiVersion: apps/v1
kind: Deployment
metadata:
	name: my-app     # ← karakter tab di sini → ParseError

# BENAR — hanya spasi
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app      # ← dua spasi

Pesan error yang akan Anda lihat bervariasi menurut library. Di PyYAML Python:

yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token

Di yaml.v3 Go:

yaml: line 4: found character that cannot start any token

Konfigurasikan editor Anda untuk memperluas tab menjadi spasi untuk file YAML. Di VS Code, tambahkan ke pengaturan workspace Anda: "[yaml]": { "editor.insertSpaces": true, "editor.tabSize": 2 }.

Konvensi: 2 vs 4 spasi. Keduanya valid. Konvensi ekosistem berbeda:

EkosistemKonvensiAlasan
Manifest Kubernetes2 spasiDokumen dan contoh resmi menggunakan 2
Chart Helm2 spasiMengikuti konvensi K8s
Docker Compose2 spasiContoh spesifikasi compose resmi
GitHub Actions2 spasiContoh workflow resmi
Playbook Ansible2 spasiDokumentasi resmi
Konfigurasi tradisional4 spasiSesuai default JSON beautify

Untuk file apa pun yang akan dikonsumsi oleh Kubernetes atau Docker Compose, gunakan 2 spasi. Untuk file konfigurasi mandiri yang hanya akan dibaca oleh manusia dan tooling kustom, keduanya bisa — cukup konsisten dalam satu file. Konverter JSON ke YAML kami menggunakan indentasi 2 spasi sebagai default dan memungkinkan Anda beralih ke 4 untuk proyek yang lebih menyukainya.

Satu aturan lagi: elemen anak harus diindentasi lebih dari induk mereka, tetapi jumlah spasi tambahan dapat berupa bilangan bulat positif apa pun (1, 2, 3, 4…) — selama konsisten dalam satu blok. Dalam praktiknya, selalu gunakan 2 atau 4 untuk keterbacaan.

Penanganan Angka di JSON ↔ YAML

Kedua format mendukung angka, tetapi edge case-nya cukup berbeda untuk menyebabkan bug produksi.

Kehilangan Presisi untuk Angka Besar

Tipe Number JavaScript adalah float IEEE 754 64-bit. Ia dapat merepresentasikan bilangan bulat secara tepat hingga 2^53 − 1 = 9.007.199.254.740.991. Di luar itu, presisi bilangan bulat hilang:

// Kehilangan presisi JavaScript — ini bukan masalah YAML, tetapi mempengaruhi parsing JSON
JSON.parse('{"v": 9007199254740993}').v
// → 9007199254740992   (3 menjadi 2 — satu bit hilang)

// Aman — dalam rentang 2^53
JSON.parse('{"v": 9007199254740991}').v
// → 9007199254740991   (tepat)

Ini penting untuk konversi JSON-ke-YAML di lingkungan JavaScript karena presisi sudah hilang sebelum serialisasi YAML dimulai. Kubernetes metadata.resourceVersion adalah field string khusus karena versi resource dapat melebihi rentang bilangan bulat aman. Field lain yang terlihat seperti angka kecil — observedGeneration, komponen uid — lebih aman, tetapi field int64 apa pun dalam respons K8s berpotensi terpengaruh.

Solusi:

  • Gunakan Python atau Go untuk pipeline konversi yang melibatkan angka besar — keduanya menangani bilangan bulat arbitrer secara native.
  • Di Node.js, gunakan parser JSON yang mendukung BigInt: JSON.parse(text, (_, v) => typeof v === 'number' && !Number.isSafeInteger(v) ? BigInt(v) : v).
  • Untuk field yang harus round-trip tanpa kehilangan, serialisasikan sebagai string di sumber.
  • Saat meninjau YAML yang dikonversi, cari field seperti resourceVersion, generation, dan nilai turunan timestamp.

Keanehan Oktal & Hex

YAML 1.1 memperlakukan string tertentu yang mirip angka sebagai bilangan bulat non-desimal:

# Kejutan parsing YAML 1.1
permissions: 0755   # diparsing sebagai oktal 493, bukan desimal 755
value: 0x1A         # diparsing sebagai hex 26, bukan string "0x1A"

# Perilaku YAML 1.2
permissions: 0755   # tetap sebagai bilangan bulat 755 (desimal) — oktal memerlukan prefiks 0o
permissions: 0o755  # diparsing sebagai oktal 493 di 1.1 dan 1.2

# Aman untuk kedua spesifikasi — kutip nilai dengan awalan nol
permissions: "0755"  # selalu string "0755"

Jebakan oktal sangat berbahaya untuk izin file Unix, komponen alamat IP dengan awalan nol (beberapa perangkat jaringan), dan kode numerik apa pun yang menggunakan awalan nol untuk padding (kode pos, kode produk). Selalu kutip nilai-nilai ini saat menulis YAML tangan, atau pastikan konverter Anda mengutipnya — konverter JSON ke YAML kami mendeteksi string numerik dari JSON dan mempertahankan tipe string-nya.

Konversi Dunia Nyata

Masalah Norway dan strategi pengutipan menjadi konkret ketika Anda menerapkannya pada skenario konversi nyata.

Manifest Kubernetes dari JSON

Workflow kanonik: kubectl get deploy my-app -o json memberikan objek langsung sebagai JSON. Anda ingin membersihkannya (hapus status, creationTimestamp, field yang dikelola) dan meng-check-in ke git sebagai manifest YAML.

JSON sumber (disingkat):

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "my-app",
    "namespace": "production",
    "labels": {
      "app": "my-app",
      "region": "NO"
    }
  },
  "spec": {
    "replicas": 3,
    "selector": {
      "matchLabels": { "app": "my-app" }
    },
    "template": {
      "spec": {
        "containers": [{
          "name": "app",
          "image": "registry.example.com/my-app:v1.2.3",
          "env": [
            { "name": "REGION", "value": "NO" },
            { "name": "ENABLE_FEATURE", "value": "yes" }
          ]
        }]
      }
    }
  }
}

Output YAML yang diharapkan (dengan perlindungan Norway):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  labels:
    app: my-app
    region: "NO"          # dikutip — kata Norway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
        - name: app
          image: registry.example.com/my-app:v1.2.3
          env:
            - name: REGION
              value: "NO"           # dikutip — kata Norway
            - name: ENABLE_FEATURE
              value: "yes"          # dikutip — kata Norway

Perhatikan bahwa replicas: 3 dibiarkan tanpa kutipan — ini adalah bilangan bulat yang sah yang Kubernetes harapkan sebagai angka. Kata Norway dalam labels dan nilai env dikutip. Konverter naif yang tidak menangani boolean YAML 1.1 akan diam-diam menghasilkan region: false dan value: false.

Setelah mengonversi, validasi dengan: kubectl apply --dry-run=client -f manifest.yaml. Ini menangkap error skema tanpa menyentuh cluster.

Coba konversinya di konverter JSON ke YAML kami — tempel JSON di atas dan lihat output yang aman untuk Norway seketika. Gunakan konverter YAML ke JSON kami untuk memverifikasi round-trip.

Docker Compose dari JSON

Pipeline CI/CD terkadang menghasilkan konfigurasi Docker Compose secara terprogram dari penyimpanan konfigurasi JSON, kemudian menulisnya ke disk sebagai YAML untuk dibaca developer.

Jebakan kritis — kebijakan restart:

{"restart_policy": "no"}

Dalam Compose, restart_policy: "no" adalah nilai yang valid yang berarti “jangan pernah restart container.” Tanpa kutipan dalam YAML, ini menjadi restart_policy: false, yang mungkin diperlakukan Docker Compose sebagai semantik yang sama (falsy = tidak restart) atau ditolak dengan error validasi tipe — perilakunya bervariasi menurut versi Compose. Pengutipan wajib.

Juga perhatikan: Compose v3 deploy.restart_policy.condition: "on-failure" — nilai on-failure mengandung kata on, tetapi dengan tanda hubung dan tidak ada dalam daftar pemicu, sehingga sebenarnya aman. Namun, condition: on (tanpa -failure) akan tidak cocok. Kutip nilai variabel environment di blok environment: jika bisa menjadi kata Norway.

Validasi file Compose setelah konversi: docker-compose config mem-parsing dan mengeluarkan ulang bentuk kanonik, memunculkan error tipe.

Workflow GitHub Actions

Workflow GitHub Actions adalah file YAML yang diedit tangan oleh developer. Skenario konversi paling umum adalah membaca data workflow dari GitHub API (yang mengembalikan JSON) dan mengonversinya ke file YAML lokal untuk diedit.

Field utama yang perlu diperhatikan:

# AMAN — tidak ada kata Norway dalam GitHub Actions standar
on:                        # "on" di sini adalah kunci YAML, bukan nilai — ditangani berbeda
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: |
          npm install
          npm test
        env:
          NODE_ENV: production   # aman — bukan kata Norway
          DEBUG: "off"           # kata Norway dalam nilai — perlu dikutip

Catatan: on: sebagai kunci YAML bersifat khusus — masalah Norway berlaku untuk nilai, bukan kunci. Tetapi on sebagai nilai (seperti DEBUG: on) akan memicu konversi. Blok env: patut mendapat perhatian khusus karena nilai variabel environment adalah string, tetapi banyak di antaranya adalah flag pendek yang bisa bertabrakan dengan kata Norway.

Untuk workflow yang menyertakan spesifikasi shell:, nilai yang valid (bash, pwsh, sh, python) semuanya aman dari konversi Norway. Nilai kustom harus dikutip secara proaktif.

Terraform JSON Plan → YAML

terraform show -json tfplan > plan.json menghasilkan representasi JSON terperinci tentang apa yang Terraform rencanakan untuk dibuat, dimodifikasi, atau dihancurkan. Mengonversi ini ke YAML membuatnya lebih mudah dibaca untuk review pull request dan audit kepatuhan.

terraform plan -out=tfplan
terraform show -json tfplan > plan.json
# Kemudian konversi dengan alat kami atau library

JSON plan Terraform kompleks dan dalam. Perhatian utama saat mengonversi:

  1. ID bilangan bulat besar. ID resource cloud (ID akun AWS, nomor proyek GCP) dan nilai atribut yang dihitung bisa berupa angka besar. Konversi via Python atau Go untuk menghindari kehilangan presisi float64.

  2. String batasan versi. Terraform menggunakan ~>, >=, <= dalam batasan versi provider. Ini adalah nilai string yang ditangani YAML dengan benar selama bukan kata Norway — tetapi ~> aman.

  3. Nilai konfigurasi provider. Output plan Terraform dapat mencakup nilai konfigurasi untuk resource. Jika field boolean default ke false dan direpresentasikan sebagai "no" dalam skema provider tertentu, itu adalah risiko Norway dalam perjalanan kembali ke YAML.

  4. Blok .sensitive_values. Nilai sensitif diredaksi sebagai boolean true dalam plan JSON. Ini selamat dari konversi dengan bersih karena true bukan kata Norway di versi YAML mana pun.

Konversi Terraform-ke-YAML terutama untuk tinjauan manusia, bukan untuk dimasukkan kembali ke Terraform. Jangan gunakan manifest YAML sebagai input Terraform — format native Terraform adalah HCL, dan format input JSON-nya spesifik dan didokumentasikan secara terpisah.

Contoh Kode — 4 Bahasa

Node.js (eemeli/yaml + js-yaml)

Ekosistem Node.js memiliki dua library YAML dominan dengan penanganan Norway yang berbeda secara bermakna:

// eemeli/yaml — direkomendasikan, YAML 1.2 secara default, aman Norway
import { stringify } from 'yaml';
import { readFileSync } from 'fs';

const jsonInput = readFileSync('input.json', 'utf8');
const data = JSON.parse(jsonInput);

// Default: YAML 1.2 — "NO" tetap "NO", tidak ada konversi boolean
const yamlOutput = stringify(data);
console.log(yamlOutput);
// region: NO      ← aman di 1.2, tetapi untuk kompatibilitas maksimum kutip secara eksplisit

// Paksa perilaku YAML 1.1 (untuk lingkungan K8s/Helm yang mem-parsing 1.1)
const yamlForK8s = stringify(data, { version: '1.1' });
// region: 'NO'    ← dikutip otomatis karena 1.1 akan mem-parsing NO sebagai false
console.log(yamlForK8s);
// js-yaml — tersebar luas, tetapi semantik YAML 1.1, berisiko Norway tanpa kehati-hatian
import yaml from 'js-yaml';
import { readFileSync } from 'fs';

const data = JSON.parse(readFileSync('input.json', 'utf8'));

// Default dump — kata Norway mungkin tidak dikutip
const unsafe = yaml.dump(data);
// region: NO    ← akan diparsing sebagai false jika dibaca kembali oleh parser 1.1!

// Lebih aman: gunakan skema kustom atau paksa pengutipan
const safer = yaml.dump(data, {
  schema: yaml.JSON_SCHEMA,   // membatasi ke tipe yang kompatibel JSON
  noCompatMode: false,
  lineWidth: -1,
  quotingType: '"',
  forceQuotes: false,         // hanya mengutip saat diperlukan per skema JSON
});

Untuk proyek baru, lebih suka eemeli/yaml. Default YAML 1.2-nya lebih aman, Document API-nya memberikan kontrol halus atas pengutipan, dan ia menangani fidelitas round-trip dengan lebih baik. Untuk proyek yang sudah menggunakan js-yaml, gunakan opsi JSON_SCHEMA untuk membatasi ke tipe yang aman untuk JSON.

Python (PyYAML + ruamel.yaml)

Python adalah bahasa dominan untuk tooling Kubernetes, Ansible, dan pipeline rekayasa data — semuanya pengguna YAML berat.

import json
import yaml
import sys

# PyYAML — sederhana, standar, tetapi YAML 1.1 secara default
with open('input.json') as f:
    data = json.load(f)

output = yaml.dump(data, default_flow_style=False, allow_unicode=True)
# country: 'NO'   ← PyYAML cukup pintar untuk mengutip otomatis kata Norway
# Tetapi TIDAK mengutip "yes", "no" (huruf kecil) di semua konfigurasi:
# enabled: 'yes'   ← dikutip
# tag: y           ← mungkin atau tidak dikutip tergantung versi

print(output)
import json
import sys
from ruamel.yaml import YAML

# ruamel.yaml — fidelitas round-trip, mendukung YAML 1.2, direkomendasikan untuk produksi
yaml_rt = YAML()
yaml_rt.default_flow_style = False
yaml_rt.width = 4096              # mencegah pembungkusan baris yang tidak diinginkan
yaml_rt.best_map_flow_style = False

with open('input.json') as f:
    data = json.load(f)

yaml_rt.dump(data, sys.stdout)
# Mempertahankan urutan kunci, menangani kata Norway dengan benar, mendukung anchor pada round-trip

Untuk skrip otomasi Ansible dan Kubernetes di mana Anda mengonversi respons JSON API ke manifest YAML, ruamel.yaml adalah pilihan yang lebih aman. PyYAML baik untuk skrip sederhana di mana Anda mengontrol data input dan telah memverifikasi tidak ada kata Norway yang muncul.

Go (gopkg.in/yaml.v3)

Go adalah bahasa ekosistem Kubernetes itu sendiri — kubectl, Helm, Argo, Flux, dan sebagian besar operator K8s ditulis dalam Go.

package main

import (
    "encoding/json"
    "fmt"
    "os"

    "gopkg.in/yaml.v3"
)

func main() {
    // Baca input JSON
    jsonBytes, err := os.ReadFile("input.json")
    if err != nil {
        panic(err)
    }

    // Unmarshal JSON ke dalam map generik
    var data map[string]interface{}
    if err := json.Unmarshal(jsonBytes, &data); err != nil {
        panic(err)
    }

    // Marshal ke YAML — yaml.v3 menggunakan semantik YAML 1.2
    yamlBytes, err := yaml.Marshal(data)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(yamlBytes))
    // country: "NO"     ← yaml.v3 mengutip kata Norway dengan benar
    // replicas: 3       ← bilangan bulat tetap bilangan bulat
    // enabled: true     ← boolean tetap boolean
}

yaml.v3 adalah peningkatan signifikan dibanding yaml.v2 untuk keamanan Norway. Library v2 mengikuti YAML 1.1 dan akan menulis NO tanpa kutipan; v3 mengutip nilai yang ambigu dengan benar. Jika Anda memelihara proyek Go lama yang menggunakan v2, upgrade ke v3 — API-nya sebagian besar kompatibel dan peningkatan keamanannya sepadan dengan migrasinya.

Untuk konversi type-safe dengan struct Go (daripada map[string]interface{}), gunakan tag struct:

type DeploymentLabels struct {
    App    string `yaml:"app" json:"app"`
    Region string `yaml:"region" json:"region"`
}
// yaml.Marshal pada field struct yang berisi "NO" akan mengutipnya dengan benar di v3

Bash CLI (yq + jq)

Untuk shell script dan konversi one-off cepat, yq (versi Mike Farah, mikefarah/yq) mengonversi JSON ke YAML dalam satu perintah:

# Install yq
brew install yq                         # macOS
sudo wget -qO /usr/local/bin/yq \
  https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
chmod +x /usr/local/bin/yq              # Linux

# Konversi file JSON ke YAML
yq -P < input.json > output.yaml

# Konversi dari output JSON kubectl
kubectl get deploy my-app -o json | yq -P > manifest.yaml

# Pipe melalui jq terlebih dahulu untuk filter/transform, kemudian konversi ke YAML
kubectl get deploy my-app -o json \
  | jq 'del(.status, .metadata.creationTimestamp, .metadata.managedFields)' \
  | yq -P > clean-manifest.yaml

Pipeline jq | yq adalah pola yang kuat: gunakan jq untuk manipulasi JSON (filter field, reshape struktur, query nilai) dan yq -P sebagai serializer YAML akhir. Untuk pola jq, lihat referensi jq command-line untuk 30 pola dunia nyata termasuk integrasi kubectl dan aws.

Peringatan Norway dengan yq: yq (mikefarah) menghormati tipe input dari JSON — string JSON "NO" dalam input akan diserialisasi sebagai string YAML dengan kutipan. Tetapi jika Anda menghasilkan YAML secara langsung dengan yq (bukan dari input JSON), Anda harus mengutip nilai kata Norway secara eksplisit. Gunakan konverter YAML ke JSON kami untuk memvalidasi round-trip setelah output yq.

Edge Case & Gotcha

Di luar masalah Norway, konversi JSON ↔ YAML memiliki beberapa edge case yang membingungkan engineer berpengalaman:

  1. YAML multi-dokumen (pemisah ---). Satu file YAML dapat berisi beberapa dokumen yang dipisahkan oleh ---. JSON tidak memiliki konsep yang setara. Saat mengonversi YAML multi-dokumen ke JSON, sebagian besar alat mengambil dokumen pertama saja, menggabungkan semua dokumen ke dalam array, atau error. Saat mengonversi JSON ke YAML, satu header dokumen --- ditambahkan berdasarkan konvensi. Tentukan dan dokumentasikan perilaku Anda secara eksplisit untuk pipeline yang mungkin menghadapi file multi-dokumen.

  2. Anchor dan alias YAML. YAML mendukung definisi &anchor dan referensi *alias untuk konfigurasi DRY. Saat mengonversi YAML ke JSON, anchor harus diperluas — JSON yang dihasilkan mungkin jauh lebih besar dari YAML sumber. Saat mengonversi JSON ke YAML, konverter tidak dapat merekonstruksi anchor yang tidak ada dalam aslinya. Alias adalah fitur khusus YAML.

  3. Parsing implisit timestamp. Parser YAML 1.1 mengonversi 2024-05-04 dan 2024-05-04T12:00:00Z ke objek tanggal native bahasa, bukan string. Ketika objek tanggal ini diserialisasi kembali ke JSON, outputnya tergantung pada library: beberapa menghasilkan string ISO, beberapa menghasilkan timestamp Unix, beberapa menghasilkan null. Round-tripping tanggal melalui YAML tanpa pengutipan string eksplisit ("2024-05-04") dapat diam-diam mengubah format.

  4. Tag !!binary. YAML dapat menyematkan data biner yang dikodekan base64 dengan tag !!binary. JSON tidak memiliki tipe biner — biner harus berupa string base64. Saat mengonversi YAML dengan field !!binary ke JSON, dekode ke string base64. Saat mengonversi kembali, Anda tidak dapat merekonstruksi tag biner tanpa mengetahui skemanya. Kubernetes menggunakan !!binary untuk beberapa nilai secret.

  5. Tabrakan tipe kunci. JSON mengharuskan kunci objek berupa string. YAML mengizinkan kunci dari tipe apa pun — kunci bilangan bulat, kunci boolean, bahkan kunci objek kompleks. File YAML dengan true: value atau 1: value sebagai kunci tidak dapat direpresentasikan secara setia sebagai JSON. Sebagian besar konverter mengubah kunci menjadi string, tetapi semantiknya berubah.

  6. Varian representasi null. Dalam YAML, null, ~, Null, NULL, dan nilai kosong semuanya berarti null. Dalam JSON, hanya null yang null. Saat mengonversi YAML ke JSON, semua ini dinormalisasi ke null. Tetapi saat mengonversi JSON kembali ke YAML, pilihan representasi null penting — ~ lebih ringkas, null lebih eksplisit. Pilih satu dan tetap konsisten.

  7. Perubahan urutan kunci. Objek JSON secara teknis tidak memiliki urutan kunci yang ditentukan (meskipun sebagian besar parser mempertahankan urutan penyisipan). Pemetaan YAML juga tidak memiliki urutan yang diperlukan. Tetapi beberapa library YAML mengurutkan kunci secara alfabetis secara default saat serialisasi. Ini dapat menyebabkan diff besar dalam version control jika JSON sumber menggunakan urutan yang berbeda. Konfigurasikan sort_keys=False di PyYAML dan opsi yang setara di library lain.

Kapan TIDAK Mengonversi

Konversi tidak selalu merupakan jawaban yang tepat. Berikut skenario di mana tetap dalam format asli adalah pilihan yang lebih baik:

Jangan konversi YAML ke JSON jika YAML berisi komentar yang mendokumentasikan logika bisnis. Komentar YAML bukan bagian dari model data — komentar menghilang dalam serialisasi apa pun ke JSON. Jika manifest Kubernetes memiliki komentar yang menjelaskan mengapa batas resource tertentu dipilih atau mengapa pengecualian kebijakan keamanan dibuat, mengonversi ke JSON menghancurkan dokumentasi itu. Pertahankan YAML.

Jangan auto-konversi konfigurasi dalam pipeline CI tanpa uji round-trip. Jika pipeline Anda mengonversi JSON ke YAML dan kemudian menerapkan YAML ke cluster, tambahkan langkah validasi round-trip: YAML kembali ke JSON, kemudian bandingkan dengan yang asli. Ini menangkap kejutan konversi tipe sebelum mencapai produksi.

Jangan konversi hanya karena alat menghasilkan JSON. kubectl, aws, terraform, dan docker inspect semuanya menghasilkan JSON, tetapi sebagian besar alat ini juga menerima YAML sebagai input. Sebelum membangun langkah konversi, periksa apakah alat target dapat langsung menerima input YAML — sebagian besar alat DevOps modern dapat. Konverter YAML ke JSON kami paling berguna ketika Anda secara khusus membutuhkan JSON untuk alat yang tidak menerima YAML.

Jangan konversi jika skemanya berbeda. Jika JSON Anda menggunakan kunci camelCase dan konsumen YAML Anda mengharapkan snake_case (atau sebaliknya), Anda memerlukan langkah transform selain konversi format. Konversi format semata akan menghasilkan YAML yang benar secara sintaktis tetapi salah secara semantis. Tangani pemetaan skema secara eksplisit.

Jangan pertahankan kedua format secara manual. Jika Anda memelihara config.json dan config.yaml yang seharusnya setara, Anda akan mengalami drift. Pilih satu format kanonik dan turunkan yang lain secara otomatis — atau lebih baik, pilih satu format dan hilangkan duplikasi.

FAQ

Apakah masalah Norway YAML masih mempengaruhi sistem modern?

Ya — ini meresap di seluruh ekosistem. Kubernetes dan Helm menggunakan library yaml.v2 Go (semantik YAML 1.1) di bagian signifikan codebase mereka. Ansible menggunakan PyYAML (YAML 1.1). Workflow GitHub Actions diparsing oleh parser YAML internal GitHub yang memiliki perilakunya sendiri. Sebagian besar file YAML CI/CD di dunia nyata diproses oleh parser YAML 1.1. Asumsikan semantik 1.1 sampai Anda memverifikasi sebaliknya.

Mengapa saya mengonversi JSON ke YAML jika YAML lebih sulit diparsing?

Konversinya bukan tentang kesulitan parser — ini tentang keterbacaan yang dapat diedit manusia. JSON ideal untuk mesin; YAML ideal untuk manusia yang perlu membaca, mengedit, dan meninjau file konfigurasi. Manifest Kubernetes yang di-check-in ke git, ditinjau dalam pull request, dan disetel tangan oleh engineer harus berupa YAML. Manifest yang sama yang diambil dari API untuk pemrosesan terprogram harus berupa JSON. Konverter JSON ke YAML kami menjembatani keduanya.

Bisakah saya round-trip JSON ↔ YAML tanpa kehilangan?

Dengan pengecualian, ya — untuk data yang kompatibel dengan JSON. JSON adalah subset dari YAML 1.2, sehingga setiap dokumen JSON yang valid adalah YAML 1.2 yang valid. Pergi JSON → YAML → JSON seharusnya tanpa kehilangan untuk data apa pun tanpa konversi tipe implisit. Masalah Norway berarti string JSON "NO" dapat bertahan dalam pass maju hanya jika konverter mengutipnya, dan kemudian bertahan dalam pass balik hanya jika parser YAML menghormati kutipan. Gunakan library YAML 1.2 untuk kedua arah untuk menjamin round-trip tanpa kehilangan.

Apa library YAML paling aman untuk produksi?

Untuk Python: ruamel.yaml dikonfigurasi untuk YAML 1.2. Untuk Node.js: eemeli/yaml (paket yaml di npm). Untuk Go: gopkg.in/yaml.v3. Ketiganya mengimplementasikan semantik YAML 1.2 atau memiliki mode YAML 1.2 eksplisit dan menangani kata Norway dengan benar. Hindari library YAML 1.1 dalam proyek baru. Jika Anda harus menggunakan library 1.1 (PyYAML, js-yaml, yaml.v2) karena alasan kompatibilitas, selalu kutip string yang rentan terhadap Norway secara eksplisit.

Apakah manifest YAML Kubernetes mendukung komentar setelah konversi JSON?

Tidak — komentar tidak dapat dipulihkan dari JSON. JSON tidak memiliki sintaks komentar, jadi tidak ada yang perlu dikonversi. Ketika Anda menjalankan kubectl get deploy -o json dan mengonversi output ke YAML untuk penyimpanan git, YAML yang dihasilkan tidak akan memiliki komentar. Komentar dalam manifest Kubernetes harus ditulis oleh manusia setelah konversi. Inilah salah satu alasan mengapa mempertahankan YAML yang ditulis tangan sebagai sumber kanonik sering lebih disukai daripada round-tripping melalui JSON API.

Bagaimana cara menangani bilangan bulat besar seperti resourceVersion atau timestamp nanodetik?

Kubernetes metadata.resourceVersion adalah field string dengan sengaja — tim Kubernetes tahu bahwa parser JSON dalam JavaScript dan runtime berbasis float64 lainnya akan kehilangan presisi pada bilangan bulat besar. Selalu perlakukan sebagai string. Untuk bilangan bulat besar yang benar-benar numerik (seperti timestamp epoch nanodetik dalam beberapa sistem tracing), gunakan tipe int Python, int64 Go, atau BigInt Node.js untuk parsing. Jangan pernah melewatkannya melalui JSON.parse() dalam JavaScript tanpa fungsi reviver kustom. Saat mengonversi ke YAML, bilangan bulat besar ini aman — YAML tidak memiliki batas presisi untuk bilangan bulat. Bahayanya ada dalam round-trip kembali melalui parser JSON JavaScript.

Apakah YAML 1.2 sudah banyak diadopsi?

Tidak merata. Library bahasa utama telah bermigrasi: yaml.v3 Go, ruamel.yaml Python, dan eemeli/yaml Node.js semuanya mendukung atau default ke YAML 1.2. Tetapi Kubernetes, Ansible, dan sebagian besar ekosistem DevOps masih berjalan pada parser YAML 1.1 karena biaya kompatibilitas mundur dari migrasi. Adopsi YAML 1.2 dalam proyek baru direkomendasikan, tetapi asumsikan 1.1 untuk sistem mana pun yang tidak Anda konfigurasi sendiri.

Haruskah tim kami menstandarkan JSON atau YAML untuk konfigurasi?

Standarkan berdasarkan tujuan, bukan format. Gunakan JSON untuk konfigurasi yang dikonsumsi oleh kode (badan permintaan API, file konfigurasi SDK, tooling terprogram). Gunakan YAML untuk konfigurasi yang dikonsumsi oleh manusia (manifest Kubernetes, pipeline CI, konfigurasi deployment, playbook Ansible). Hindari mencampur keduanya untuk konfigurasi yang sama — pilih satu representasi per tipe konfigurasi dan otomatasikan konversinya jika Anda membutuhkan keduanya. Ketika Anda perlu mengonversi, baik JSON ke YAML maupun YAML ke JSON kami berjalan sepenuhnya di browser Anda — tidak ada data yang meninggalkan perangkat Anda.

Coba Sekarang

Siap mengonversi file nyata? Coba konverter JSON ke YAML kami untuk memurnikan JSON menjadi YAML Kubernetes yang aman — ia secara otomatis mengutip kata Norway (NO, yes, on, off, dan daftar boolean YAML 1.1 lengkap) dan memungkinkan Anda memilih indentasi 2 spasi atau 4 spasi. Untuk arah sebaliknya, konverter YAML ke JSON kami menangani anchor, alias, dan YAML multi-dokumen. Kedua alat berjalan sepenuhnya di browser Anda — data Anda tidak pernah meninggalkan perangkat, yang penting ketika Anda bekerja dengan manifest Kubernetes produksi atau Terraform plan yang berisi konfigurasi resource sensitif.

Artikel Terkait

Lihat semua artikel