ToolHub
View All Posts

Thực Hành Tốt Nhất Về Định Dạng JSON

JSON (JavaScript Object Notation) đã trở thành tiêu chuẩn thực tế cho trao đổi dữ liệu trên web. API trả về JSON, file cấu hình sử dụng JSON, thậm chí cơ sở dữ liệu cũng lưu trữ tài liệu JSON. Mặc dù JSON đơn giản, nó có các quy tắc cú pháp nghiêm ngặt dễ bị vi phạm, và JSON định dạng không đúng dẫn đến khó gỡ lỗi, vấn đề hiệu suất và lỗ hổng bảo mật. Hướng dẫn này bao gồm mọi thứ bạn cần biết về định dạng JSON đúng cách, từ cú pháp cơ bản đến xác thực Schema và xử lý file lớn.

JSON Là Gì?

JSON là định dạng trao đổi dữ liệu dựa trên văn bản, nhẹ, bắt nguồn từ cú pháp object literal của JavaScript. Nó được Douglas Crockford chỉ định vào đầu những năm 2000 và được chuẩn hóa thành ECMA-404 và RFC 8259. Mục tiêu thiết kế của JSON là tính đơn giản, khả năng đọc của con người và dễ triển khai trên các ngôn ngữ lập trình. Ngày nay, mọi ngôn ngữ lập trình chính đều có hỗ trợ JSON tích hợp.

JSON hỗ trợ sáu kiểu dữ liệu: chuỗi (dấu ngoặc kép), số (số nguyên và số thực), boolean (true và false), null, đối tượng (tập hợp khóa-giá trị không có thứ tự) và mảng (danh sách có thứ tự). Nó không hỗ trợ chú thích, ngày tháng, dữ liệu nhị phân hoặc giá trị undefined.

Quy Tắc Cú Pháp JSON

JSON có cú pháp phải được tuân thủ nghiêm ngặt. Chỉ một lỗi ký tự cũng có thể khiến toàn bộ tài liệu không phân tích được. Hiểu các quy tắc này ngăn chặn các lỗi định dạng phổ biến nhất.

Chuỗi Phải Dùng Dấu Ngoặc Kép

Tất cả giá trị chuỗi và khóa đối tượng phải được đặt trong dấu ngoặc kép. Dấu ngoặc đơn không phải là dấu phân cách chuỗi JSON hợp lệ. Đây là một trong những lỗi phổ biến nhất của nhà phát triển chuyển từ JavaScript, nơi dấu ngoặc đơn và ngoặc kép có thể dùng thay thế cho nhau.

// Invalid - single quotes
{'name': 'Alice', 'age': 30}

// Valid - double quotes
{"name": "Alice", "age": 30}

Khóa Đối Tượng Phải Được Đặt Trong Dấu Ngoặc Kép

Không giống JavaScript object literal, JSON yêu cầu tất cả khóa đối tượng phải được đặt trong dấu ngoặc kép. Khóa không được đặt trong dấu ngoặc kép là lỗi cú pháp.

// Invalid - unquoted keys
{name: "Alice", age: 30}

// Valid - quoted keys
{"name": "Alice", "age": 30}

Không Được Có Dấu Phẩy Cuối Cùng

JSON không cho phép dấu phẩy sau mục cuối cùng trong đối tượng hoặc mảng. Đây là một lỗi phổ biến khác của nhà phát triển JavaScript, nơi dấu phẩy cuối cùng được cho phép (và thậm chí được khuyến khích trong một số style guide).

// Invalid - trailing comma
{
  "name": "Alice",
  "age": 30,
}

// Valid - no trailing comma
{
  "name": "Alice",
  "age": 30
}

Không Hỗ Trợ Chú Thích

JSON không hỗ trợ chú thích. Cả // chú thích một dòng và /* */ chú thích nhiều dòng đều không hợp lệ trong JSON. Nếu bạn cần bao gồm tài liệu, hãy cân nhắc sử dụng file tài liệu riêng hoặc định dạng JSONC (JSON with Comments) được một số công cụ hỗ trợ.

Kiểu Giá Trị Nghiêm Ngặt

Giá trị JSON phải là một trong sáu kiểu được hỗ trợ. undefined, NaN, Infinity và -Infinity không phải là giá trị JSON hợp lệ. Bao gồm bất kỳ giá trị nào trong số này sẽ gây ra lỗi phân tích cú pháp hoặc tạo ra JSON không chuẩn mà nhiều trình phân tích sẽ từ chối.

Lỗi Định Dạng Phổ Biến

Hai chế độ định dạng chính của JSON phục vụ các mục đích khác nhau, và sử dụng đúng định dạng trong đúng ngữ cảnh là quan trọng.

Pretty Print và Minify

Pretty print thêm thụt lề và xuống dòng để làm cho JSON có thể đọc được đối với con người. Điều này rất quan trọng trong quá trình phát triển, gỡ lỗi và viết tài liệu. Hầu hết các trình định dạng JSON sử dụng thụt lề 2 khoảng trắng theo mặc định.

JSON Pretty Print

Minify loại bỏ tất cả khoảng trắng không cần thiết, tạo ra JSON hợp lệ nhỏ nhất có thể. Điều này rất quan trọng cho API production nơi mỗi byte đều quan trọng.

{
  "users": [
    {
      "id": 1,
      "name": "Alice",
      "email": "alice@example.com"
    },
    {
      "id": 2,
      "name": "Bob",
      "email": "bob@example.com"
    }
  ]
}

JSON Minified

Mặc dù xác thực cú pháp JSON kiểm tra xem tài liệu có đúng định dạng không, nó không xác thực dữ liệu có cấu trúc, kiểu hoặc giá trị mong đợi không. JSON Schema lấp đầy khoảng trống này bằng cách cung cấp từ vựng để mô tả hình dạng mong đợi của dữ liệu JSON.

{"users":[{"id":1,"name":"Alice","email":"alice@example.com"},{"id":2,"name":"Bob","email":"bob@example.com"}]}

Khi Nào Sử Dụng Loại Nào

Ngữ CảnhĐịnh DạngLý Do
Phát triển và gỡ lỗiPretty printKhả năng đọc và quét nhanh
File cấu hìnhPretty printCon người cần đọc và chỉnh sửa các file này
Phản hồi API productionMinifiedTải nhỏ hơn, truyền tải nhanh hơn
File logMinified (mỗi dòng một đối tượng)Lưu trữ gọn, dễ grep
Version controlPretty printDiff có ý nghĩa và ít xung đột merge hơn
Thực hành tốt nhất: Luôn lưu trữ JSON ở dạng đã định dạng trong version control. Chạy minify như một bước build trước khi triển khai. Bằng cách này, bạn có được diff có thể đọc được trong khi vẫn có lợi ích hiệu suất của JSON minified trong production.

Xác Thực JSON Schema

JSON Schema là một tài liệu JSON mô tả cấu trúc của các tài liệu JSON khác. Nó cho phép bạn chỉ định các trường bắt buộc, kiểu mong đợi, phạm vi giá trị, mẫu chuỗi và cấu trúc đối tượng lồng nhau. Một tài liệu JSON phù hợp với Schema được gọi là instance hợp lệ.

JSON Schema Là Gì?

Bạn nên sử dụng xác thực JSON Schema bất cứ khi nào nhận JSON từ nguồn bên ngoài: body yêu cầu API, file cấu hình, nhập dữ liệu và tải message queue. Xác thực Schema có thể phát hiện lỗi sớm, cung cấp thông báo lỗi rõ ràng và hoạt động như tài liệu sống cho định dạng dữ liệu. Các thư viện như Ajv (JavaScript), jsonschema (Python) và json-schema-validator (Java) giúp dễ dàng tích hợp xác thực Schema vào bất kỳ ứng dụng nào.

Các Tính Năng Schema Phổ Biến

Khi Nào Sử Dụng Xác Thực Schema

Kích thước của tài liệu JSON ảnh hưởng trực tiếp đến hiệu suất ứng dụng theo nhiều cách: thời gian truyền tải mạng, thời gian phân tích cú pháp và tiêu thụ bộ nhớ. Hiểu những tác động này giúp bạn đưa ra quyết định sáng suốt về định dạng và cấu trúc JSON.

Tác Động Hiệu Suất Của Kích Thước JSON

Mỗi byte JSON phải di chuyển qua mạng từ server đến client. Sự khác biệt giữa 10KB và 100KB có vẻ nhỏ trên kết nối nhanh, nhưng trên mạng di động hoặc đối với người dùng ở khu vực internet chậm, tác động là đáng kể. Nghiên cứu cho thấy mỗi 100ms thời gian tải tăng thêm làm giảm tỷ lệ chuyển đổi khoảng 1%. Nén thường giảm kích thước JSON 30-50%, nén gzip giảm thêm 70-85%. Luôn bật nén gzip hoặc Brotli cho phản hồi API JSON.

Truyền Tải Mạng

Phân tích cú pháp JSON tốn kém đáng ngạc nhiên. Đối với tài liệu lớn (trên 1MB), việc phân tích trên thiết bị di động có thể mất hàng trăm mili giây. Chi phí gần như tuyến tính với kích thước tài liệu. Các chiến lược chính để giảm chi phí phân tích cú pháp bao gồm: chỉ gửi dữ liệu client cần (lọc trường), phân trang cho tập kết quả lớn và sử dụng định dạng tuần tự hóa hiệu quả hơn như Protocol Buffers hoặc MessagePack cho giao tiếp giữa các dịch vụ nội bộ không cần khả năng đọc của con người.

Hiệu Suất Phân Tích Cú Pháp

JSON đã phân tích thường tiêu thụ bộ nhớ gấp 3-10 lần so với dạng tuần tự hóa, vì mỗi giá trị trở thành một đối tượng riêng biệt với phân bổ bộ nhớ riêng. Chuỗi JSON 1MB sau khi phân tích có thể sử dụng 5-10MB RAM. Đối với ứng dụng JavaScript chạy trong trình duyệt có bộ nhớ hạn chế, điều này có thể dẫn đến suy giảm hiệu suất hoặc crash trên thiết bị cấp thấp.

Sử Dụng Bộ Nhớ

JSON Lines (JSONL hoặc NDJSON) là định dạng liên quan giải quyết một hạn chế chính của JSON: yêu cầu phân tích toàn bộ tài liệu như một đơn vị duy nhất. Trong JSONL, mỗi dòng của file là một đối tượng JSON hoàn chỉnh, độc lập.

JSON và JSONL

File JSON lớn (trên 10MB) đặt ra thách thức đặc biệt đòi hỏi xử lý đặc biệt. Phương pháp phân tích tiêu chuẩn có thể thất bại hoặc hoạt động kém ở quy mô này.

Khi Nào Sử Dụng JSONL

Khi Nào Sử Dụng JSON Tiêu Chuẩn

Xử Lý File JSON Lớn

Trình phân tích streaming (hoặc kiểu SAX) xử lý JSON tăng dần mà không cần tải toàn bộ tài liệu vào bộ nhớ. Chúng phát ra sự kiện khi gặp các phần tử cấu trúc như bắt đầu đối tượng, cặp khóa-giá trị và mục mảng. Phương pháp này sử dụng bộ nhớ không đổi bất kể kích thước file. Các thư viện như oboe.js (JavaScript), ijson (Python) và Jackson Streaming API (Java) cung cấp phân tích JSON streaming.

Trình Phân Tích Cú Pháp Streaming

Mặc dù JSON là định dạng dữ liệu và bản thân không không an toàn, cách ứng dụng xử lý JSON có thể tạo ra lỗ hổng. Hiểu những rủi ro này là điều cần thiết để xây dựng hệ thống an toàn.

Mẹo Thực Tế Cho File Lớn

Lưu Ý Bảo Mật JSON

Quy tắc bảo mật quan trọng nhất: không bao giờ sử dụng hàm eval() của JavaScript để phân tích JSON. eval() thực thi mã JavaScript tùy ý, có nghĩa là tải JSON độc hại có thể chạy code trên máy người dùng. Luôn sử dụng JSON.parse(), chỉ phân tích JSON hợp lệ và từ chối mọi code thực thi. Điều này là không thể thương lượng.

Không Bao Giờ Dùng eval() Để Phân Tích JSON

JSONP (JSON with Padding) là kỹ thuật được sử dụng trước khi CORS được hỗ trợ rộng rãi để vượt qua hạn chế same-origin policy. Nó hoạt động bằng cách bọc dữ liệu JSON trong một lời gọi hàm được thực thi dưới dạng script. Điều này vốn nguy hiểm vì nó thực thi JavaScript tùy ý từ server bên thứ ba. Nếu bạn kiểm soát cả client và server, hãy sử dụng CORS thay vì JSONP. JSONP nên được coi là công nghệ cũ và nên tránh trong ứng dụng mới.

JSONP và Rủi Ro Cross-Domain

Khi merge hoặc deep copy đối tượng JSON trong JavaScript, hãy cảnh giác với các khóa như __proto__, constructor và prototype. Nếu JSON do người dùng cung cấp được merge đệ quy vào đối tượng hiện có mà không làm sạch các khóa này, nó có thể sửa đổi prototype của tất cả đối tượng trong ứng dụng, dẫn đến leo thang đặc quyền hoặc từ chối dịch vụ. Luôn làm sạch khóa đối tượng trước khi merge.

Prototype Pollution

Tài liệu JSON được xây dựng cẩn thận với độ sâu lồng ghép cực cao (hàng nghìn cấp) có thể gây ra lỗi stack overflow trong trình phân tích đệ quy. Giảm thiểu bằng cách đặt độ sâu lồng tối đa trong trình phân tích. Hầu hết trình phân tích JSON production cho phép bạn cấu hình giới hạn này.

Từ Chối Dịch Vụ Qua Lồng Ghép Sâu

Không bao giờ tin tưởng dữ liệu JSON từ nguồn bên ngoài. Luôn xác thực cấu trúc, kiểu và phạm vi giá trị của JSON đến trước khi sử dụng. Xác thực JSON Schema là phương pháp mạnh mẽ nhất, nhưng ngay cả kiểm tra đơn giản về trường bắt buộc và xác nhận kiểu cũng cung cấp bảo vệ đáng kể chống lại đầu vào không đúng định dạng hoặc độc hại.

Xác Thực Đầu Vào

Cần định dạng, xác thực hoặc nén JSON? Hãy dùng thử công cụ JSON trực tuyến miễn phí của chúng tôi. Tất cả xử lý diễn ra trong trình duyệt của bạn, đảm bảo tốc độ và quyền riêng tư tối đa.

JSON pretty print chứa khoảng trắng (thụt lề, xuống dòng) để con người đọc, trong khi JSON minified loại bỏ tất cả khoảng trắng không cần thiết để giảm thiểu kích thước file. Sử dụng JSON pretty print trong quá trình phát triển và gỡ lỗi, sử dụng JSON minified trong môi trường production để có tải mạng nhỏ hơn và phân tích nhanh hơn.

Công Cụ Định Dạng JSONTrình Xác Thực JSON

Câu Hỏi Thường Gặp

Sự khác biệt giữa JSON pretty print và minified là gì?

Các lỗi phổ biến nhất là: dấu phẩy cuối cùng sau mục cuối của đối tượng hoặc mảng, sử dụng dấu ngoặc đơn thay vì dấu ngoặc kép cho chuỗi, thêm chú thích (JSON không hỗ trợ chú thích), sử dụng khóa đối tượng không đặt trong dấu ngoặc kép và bao gồm các giá trị không hợp lệ như undefined hoặc NaN.

Các lỗi định dạng JSON phổ biến nhất là gì?

Sử dụng JSONL (JSON Lines) khi bạn cần xử lý bản ghi tăng dần, như file log, luồng dữ liệu hoặc tập dữ liệu lớn không thể nạp vào bộ nhớ. Mỗi dòng là một đối tượng JSON hoàn chỉnh, vì vậy bạn có thể đọc và phân tích từng dòng một mà không cần tải toàn bộ file. JSON tiêu chuẩn yêu cầu phân tích toàn bộ tài liệu trước khi truy cập bất kỳ dữ liệu nào.

Khi nào nên sử dụng JSONL thay vì JSON?

Sử dụng JSON Schema để định nghĩa cấu trúc mong đợi của dữ liệu JSON, sau đó sử dụng các thư viện như Ajv (JavaScript), jsonschema (Python) hoặc trình xác thực trực tuyến để xác thực instance theo Schema đó. JSON Schema cho phép bạn chỉ định trường bắt buộc, kiểu, phạm vi giá trị, mẫu chuỗi và cấu trúc đối tượng lồng nhau.

Làm thế nào để xác thực JSON theo Schema?

Bản thân JSON là định dạng dữ liệu, không an toàn cũng không không an toàn. Tuy nhiên, cách bạn phân tích và sử dụng JSON có thể tạo ra lỗ hổng. Rủi ro chính là sử dụng eval() để phân tích JSON (không bao giờ làm điều này — luôn sử dụng JSON.parse()). Ngoài ra, hãy cảnh giác với JSONP, có thể vượt qua same-origin policy. Luôn xác thực và làm sạch dữ liệu JSON từ nguồn không tin cậy trước khi sử dụng.

JSON có an toàn cho trao đổi dữ liệu không?

JSON itself is a data format and is neither secure nor insecure. However, how you parse and use JSON can introduce vulnerabilities. The main risk is using eval() to parse JSON (never do this �?always use JSON.parse()). Also be cautious with JSONP, which can bypass same-origin policies. Always validate and sanitize JSON data from untrusted sources before using it.