YAML dễ viết vì gần như không có dấu câu. Chính đặc điểm đó khiến ta dễ viết ra thứ có nghĩa khác với những gì mắt thấy. Phần lớn lỗi YAML không phải lỗi cú pháp: tệp vẫn đọc được, chỉ là một giá trị âm thầm đổi kiểu. Bài này đi qua những cái bẫy từng gây sự cố thật, kèm đầu ra chính xác của bộ phân tích cho từng trường hợp, rồi kết thúc bằng một quy trình ngắn để chuyển YAML sang JSON mà không bị bất ngờ. Mọi ví dụ đều có thể dán vào công cụ chuyển YAML ⇄ JSON.
Hai phiên bản YAML vẫn đang được dùng
YAML 1.1 (2005) và YAML 1.2 (2009, bản sửa 1.2.2 năm 2021) không thống nhất cách gán kiểu cho giá trị không có nháy. YAML 1.2 dùng một "lược đồ lõi" nhỏ: true/false là boolean, null và ~ là null, thứ trông giống số là số, còn lại là chuỗi. YAML 1.1 có nhiều kiểu ngầm định hơn hẳn. Vấn đề là một phần lớn phần mềm đọc YAML của bạn vẫn theo luật 1.1, chẳng hạn PyYAML và các thư viện Ruby, Go đời cũ. Vì vậy cùng một tệp có thể mang hai nghĩa khác nhau tùy chương trình đọc nó.
Vấn đề Na Uy
Đây là một danh sách mã quốc gia:
countries: [GB, IE, NO, SE]Bộ đọc YAML 1.2 thấy bốn chuỗi. Bộ đọc YAML 1.1 thấy "GB", "IE", false, "SE", vì trong 1.1 các từ y, yes, n, no, on và off (viết thường, viết hoa chữ đầu hoặc viết hoa toàn bộ) là boolean. Điều tương tự xảy ra với cờ tính năng đặt là on, trường trả lời đặt là no, hay thiết lập tên Y. Công cụ chuyển đổi cảnh báo từng trường hợp kèm số dòng, dù theo 1.2 chúng là chuỗi hợp lệ.
Cách sửa là đặt trong nháy: [GB, IE, "NO", SE] được đọc giống nhau ở mọi nơi. Khi công cụ viết YAML từ JSON, nó đặt trong nháy mọi chuỗi mà bất kỳ phiên bản nào có thể hiểu sai, vì thế "NO", "on" và "yes" ra kèm dấu nháy.
Những con số không như vẻ ngoài
- Số 0 đứng đầu.
mode: 0644là số 644 trong YAML 1.2, nhưng là số bát phân 0644, tức 420, trong YAML 1.1. Với quyền tệp, đó là khác biệt giữarw-r--r--và một quyền vô nghĩa. Hãy viết0o644(bát phân kiểu YAML 1.2), hoặc tốt hơn, đặt trong nháy và chuyển đổi trong mã. - Chuỗi phiên bản.
version: 1.10là số thực 1.1. Bản phát hành "1.10" thành "1.1" ngay khi một chương trình đọc nó như số. Hãy đặt phiên bản trong nháy. - Giờ.
start: 12:30từng là số hệ 60 bằng 750 trong YAML 1.1 (12 × 60 + 30); trong 1.2 nó là chuỗi. Hãy đặt trong nháy. - Số nguyên lớn.
id: 12345678901234567890là số nguyên hợp lệ, nhưng JavaScript, và vì thế đa số công cụ JSON, không lưu chính xác được: nó thành 12345678901234567000. Công cụ giữ nguyên các chữ số trong văn bản JSON, nhưng chương trình đọc JSON thì chưa chắc. Hãy gửi ID dưới dạng chuỗi. - Vô cực và NaN.
.infvà.nanlà số thực YAML không có dạng JSON tương ứng; công cụ ghi chúng thànhnullvà cho biết đã thay bao nhiêu giá trị.
Thụt lề và dấu tab
Thụt lề chính là cấu trúc. Hai quy tắc hay làm người ta vấp:
- Cấm dùng tab để thụt lề. Một dấu tab chép từ trình soạn thảo làm tệp không hợp lệ, và lỗi xuất hiện ở một dòng trông hoàn toàn bình thường. Công cụ báo "Dùng phím Tab để thụt lề" kèm số dòng.
- Thụt thừa một dấu cách sẽ đổi nghĩa. Trong tệp sau, dòng
ckhông thuộc về đâu cả:
a:
b: 1
c: 2Một giá trị thường có thể kéo dài sang dòng sau nếu dòng đó thụt sâu hơn, nên bộ phân tích đọc giá trị của b là 1 c, rồi gặp dấu hai chấm và bỏ cuộc. Lỗi chỉ vào dòng 3. Lỗi ngược lại, thiếu một dấu cách, âm thầm đẩy một khóa lên một cấp, và không bộ phân tích nào phát hiện được. Sau khi chuyển, hãy nhìn cấu trúc lồng nhau của JSON: nó cho thấy cấu trúc bạn thật sự đã viết.
Danh sách dưới một khóa có thể đặt cùng mức thụt lề với khóa hoặc sâu hơn một mức; cả hai đều hợp lệ, và tùy chọn "Thụt lề danh sách dưới khóa" quyết định công cụ viết theo kiểu nào.
Neo, bí danh và khóa gộp
Neo (&tên) và bí danh (*tên) cho phép dùng lại một khối, còn khóa gộp << chép các khóa của một ánh xạ sang ánh xạ khác:
defaults: &defaults
image: shop-api:1.8.2
replicas: 2
production:
<<: *defaults
replicas: 6Trong JSON, kết quả là hai đối tượng đầy đủ; production.replicas bằng 6, vì khóa viết tường minh luôn thắng khóa được gộp. Có hai điều cần cẩn thận. Thứ nhất, << được định nghĩa cho YAML 1.1 và không nằm trong lược đồ lõi 1.2, nên một bộ đọc 1.2 nghiêm ngặt có thể coi nó là một khóa bình thường tên <<. Thứ hai, bí danh có thể lồng nhau: chín tầng, mỗi tầng mười bí danh, trên mười chuỗi, bung ra một tỷ giá trị từ một tệp chỉ vài trăm byte. Mẫu "billion laughs" này là một kiểu tấn công từ chối dịch vụ có thật, nên công cụ đếm số giá trị được bung ra và dừng ở một triệu.
Chuyển YAML sang JSON an toàn
- Chuyển rồi đọc JSON, đừng đọc YAML. Kiểu dữ liệu trong JSON là tường minh:
falsekhác"NO",1.1khác"1.10". - Đọc các cảnh báo. Cảnh báo nghĩa là một chương trình khác có thể đọc tệp của bạn theo cách khác.
- Đặt trong nháy mọi thứ không hiển nhiên là số hay boolean: mã quốc gia, phiên bản, giờ, mã bưu chính, ID và quyền tệp.
- Kiểm tra cấu trúc lồng nhau so với ý định, nhất là sau khi sửa thụt lề bằng tay.
- Giữ chú thích ở tệp gốc. JSON không có chú thích, nên chuyển đi rồi chuyển lại sẽ mất chúng.
Những lỗi hay gặp
- Tin vào một công cụ kiểm tra YAML dùng phiên bản luật khác với chương trình thật.
- Viết
on:làm khóa trong tệp CI và nghĩ mọi công cụ đều coi nó là chuỗi "on". Một số bộ đọc YAML 1.1 biến khóa đó thànhtrue. - Dùng
yes/nocho boolean vì trông "thân thiện" hơn; hãy dùngtrue/false. - Đặt nháy cho khóa mà không cho giá trị, hoặc ngược lại, với cùng một loại dữ liệu.
- Dán YAML vào ứng dụng chat hay hệ thống quản lý công việc tự đổi dấu cách thành tab hoặc dấu cách không ngắt.
Dán tệp của bạn vào công cụ chuyển YAML ⇄ JSON để xem chính xác dữ liệu và những giá trị phụ thuộc phiên bản, và dùng công cụ định dạng JSON để xem kết quả JSON lớn.