JSON nâng cao: JSON Schema, JWT, XML, JSON5 và các công cụ xử lý JSON

JSON ban đầu được biết đến như một định dạng dữ liệu đơn giản dùng để trao đổi thông tin giữa trình duyệt và máy chủ. Tuy nhiên, khi một hệ thống phát triển từ vài API thành hàng chục hoặc hàng trăm dịch vụ, JSON không còn chỉ là những cặp key-value được đặt trong dấu ngoặc nhọn. Dữ liệu cần có cấu trúc rõ ràng, phải được kiểm tra trước khi lưu trữ, truyền qua API hoặc đưa vào các hệ thống khác.

Đó là lúc những khái niệm như JSON Schema, JWT, XMLJSON5 bắt đầu trở nên quan trọng. Mỗi công nghệ giải quyết một vấn đề khác nhau: JSON Schema giúp mô tả và xác thực cấu trúc dữ liệu, JWT phục vụ việc truyền thông tin xác thực và các claims, XML phù hợp với nhiều hệ thống cần cấu trúc tài liệu chặt chẽ, còn JSON5 mở rộng khả năng viết JSON theo hướng thuận tiện hơn cho con người.

Bên cạnh đó, hệ sinh thái JSON có rất nhiều công cụ để kiểm tra cú pháp, định dạng, chuyển đổi, truy vấn, phân tích và xử lý dữ liệu. Hiểu đúng vai trò của từng công cụ sẽ giúp lập trình viên tránh được việc sử dụng một giải pháp cho mọi tình huống.

JSON nâng cao: JSON Schema, JWT, XML, JSON5 và các công cụ xử lý JSON
JSON nâng cao: JSON Schema, JWT, XML, JSON5 và các công cụ xử lý JSON

JSON nâng cao bắt đầu từ việc hiểu đúng cấu trúc dữ liệu

JSON có ưu điểm lớn là cú pháp tương đối đơn giản và dễ đọc. Một đối tượng có thể chứa nhiều thuộc tính, mỗi thuộc tính có thể mang giá trị dạng chuỗi, số, boolean, null, object hoặc array. Chính sự linh hoạt này khiến JSON phù hợp với API, cấu hình ứng dụng và nhiều dạng dữ liệu trao đổi giữa các hệ thống.

Tuy nhiên, sự linh hoạt cũng tạo ra một vấn đề: nếu không có quy ước hoặc cơ chế kiểm tra, cùng một loại dữ liệu có thể được tạo ra theo nhiều cấu trúc khác nhau.

Ví dụ, một API về thông tin khách hàng có thể trả về:

{
  "name": "Nguyen Van A",
  "email": "a@example.com",
  "age": 30
}

Nhưng một phiên bản khác có thể vô tình sử dụng full_name thay cho name, gửi tuổi dưới dạng chuỗi hoặc bỏ hoàn toàn trường email. JSON vẫn hợp lệ về mặt cú pháp, nhưng dữ liệu có thể không còn phù hợp với yêu cầu của ứng dụng.

Vì vậy cần phân biệt hai khái niệm:

  • JSON hợp lệ: dữ liệu tuân thủ cú pháp JSON.
  • Dữ liệu hợp lệ theo nghiệp vụ: dữ liệu có cấu trúc, kiểu dữ liệu và các điều kiện phù hợp với yêu cầu của hệ thống.

JSON Schema được tạo ra để giải quyết phần thứ hai. Nó không thay thế JSON mà cung cấp một cách mô tả JSON phải có hình dạng như thế nào.

JSON Schema giúp API kiểm soát dữ liệu thay vì chỉ kiểm tra cú pháp

JSON Schema là một tiêu chuẩn dùng để mô tả cấu trúc, kiểu dữ liệu và các ràng buộc mà một tài liệu JSON cần đáp ứng. Thay vì chỉ nhìn vào dữ liệu để đoán một trường có bắt buộc hay không, hệ thống có thể dựa vào schema để xác định điều đó một cách rõ ràng.

Một schema đơn giản có thể quy định rằng đối tượng khách hàng phải có tên và email, trong đó tên là chuỗi và email phải đáp ứng định dạng email:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "age": {
      "type": "integer",
      "minimum": 0
    }
  },
  "required": ["name", "email"]
}

Điểm quan trọng là schema không phải dữ liệu khách hàng. Nó là bản mô tả quy tắc của dữ liệu. Từ schema này, công cụ validator có thể kiểm tra một JSON cụ thể có đáp ứng các quy tắc đã đặt ra hay không.

Những thành phần quan trọng trong JSON Schema

Một số keyword xuất hiện thường xuyên trong các schema thực tế gồm:

  • type: xác định kiểu dữ liệu như object, array, string, number, integer, boolean hoặc null.
  • properties: mô tả các thuộc tính bên trong một object.
  • required: xác định những thuộc tính bắt buộc phải xuất hiện.
  • items: mô tả cấu trúc của từng phần tử trong array.
  • minimum và maximum: giới hạn giá trị số.
  • minLength và maxLength: giới hạn độ dài chuỗi.
  • pattern: áp dụng biểu thức chính quy cho chuỗi.
  • enum: giới hạn giá trị vào một tập lựa chọn xác định.
  • additionalProperties: kiểm soát việc object có được phép chứa các thuộc tính ngoài danh sách đã khai báo hay không.

Nhờ những thành phần này, schema có thể đi xa hơn việc kiểm tra kiểu dữ liệu đơn thuần. Nó có thể mô tả một phần đáng kể quy tắc hình dạng của dữ liệu được trao đổi giữa các hệ thống.

Kiểm tra object và array trong cùng một cấu trúc

Trong ứng dụng thực tế, dữ liệu thường có nhiều tầng. Một đơn hàng có thông tin khách hàng, danh sách sản phẩm và thông tin thanh toán. JSON Schema có thể mô tả toàn bộ cấu trúc đó.

{
  "type": "object",
  "properties": {
    "order_id": {
      "type": "string"
    },
    "customer": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string",
          "format": "email"
        }
      },
      "required": ["name", "email"]
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": ["product_id", "quantity"]
      }
    }
  },
  "required": ["order_id", "customer", "items"]
}

Cách mô tả này đặc biệt hữu ích đối với API có dữ liệu lồng nhau. Khi cấu trúc thay đổi, schema cũng trở thành tài liệu giúp đội phát triển nhận biết chính xác thay đổi đó ảnh hưởng đến phần nào.

JSON Schema nên được dùng ở đâu trong một hệ thống thực tế?

JSON Schema có giá trị nhất khi được đặt vào đúng vị trí của quy trình xử lý dữ liệu. Nó có thể được sử dụng ở phía nhận dữ liệu để kiểm tra request, ở phía trả dữ liệu để kiểm soát response hoặc trong quá trình phát triển để làm tài liệu cho API.

Ví dụ, với một API nhận thông tin đăng ký tài khoản, máy chủ có thể kiểm tra request trước khi thực hiện các thao tác tiếp theo. Nếu trường tuổi phải là số nguyên nhưng client gửi chuỗi, request có thể bị từ chối ngay ở bước validation thay vì để lỗi tiếp tục đi sâu vào tầng nghiệp vụ.

Điều này tạo ra một lợi ích quan trọng: lỗi dữ liệu được phát hiện gần nơi nó phát sinh.

Schema cũng có thể hỗ trợ quá trình phát triển API. Khi frontend và backend cùng dựa trên một mô tả dữ liệu thống nhất, việc trao đổi giữa hai bên trở nên rõ ràng hơn. Các trường, kiểu dữ liệu và điều kiện bắt buộc không còn phụ thuộc hoàn toàn vào tài liệu viết bằng ngôn ngữ tự nhiên.

Validation không thay thế kiểm tra nghiệp vụ

Một sai lầm phổ biến là cho rằng JSON Schema có thể kiểm tra toàn bộ tính hợp lệ của dữ liệu. Trên thực tế, schema chủ yếu mô tả cấu trúc và các ràng buộc có thể biểu diễn trong schema.

Ví dụ, schema có thể quy định quantity phải là số nguyên lớn hơn hoặc bằng 1. Nhưng việc sản phẩm đó còn hàng hay không lại là vấn đề nghiệp vụ cần được kiểm tra ở tầng xử lý của ứng dụng.

Tương tự, một email có thể đúng định dạng nhưng chưa chắc là email tồn tại. Một mã sản phẩm có thể đúng kiểu chuỗi nhưng chưa chắc tồn tại trong cơ sở dữ liệu.

Do đó, một hệ thống tốt thường có nhiều lớp kiểm tra:

  1. Kiểm tra JSON có đúng cú pháp hay không.
  2. Kiểm tra cấu trúc và kiểu dữ liệu bằng schema.
  3. Kiểm tra các quy tắc nghiệp vụ trong ứng dụng.
  4. Kiểm tra quyền truy cập trước khi thực hiện thao tác.
  5. Kiểm tra dữ liệu trước khi lưu hoặc truyền sang hệ thống khác.

JSON Schema giúp quản lý thay đổi API rõ ràng hơn

Khi API còn nhỏ, việc thay đổi một trường dữ liệu có vẻ đơn giản. Nhưng khi có nhiều ứng dụng cùng sử dụng API, một thay đổi nhỏ cũng có thể tạo ra lỗi ở những client chưa được cập nhật.

Chẳng hạn, API ban đầu trả về:

{
  "id": 101,
  "name": "San pham A"
}

Sau đó backend thay đổi thành:

{
  "id": "101",
  "name": "San pham A"
}

Nhìn bằng mắt thường, hai dữ liệu gần như giống nhau. Nhưng kiểu của id đã thay đổi từ number sang string. Một client đang thực hiện phép tính hoặc xử lý ID theo kiểu số có thể gặp lỗi.

Nếu cấu trúc response được mô tả bằng schema và được kiểm tra trong quy trình phát triển, những thay đổi kiểu dữ liệu như vậy dễ được phát hiện hơn.

Đây cũng là lý do JSON Schema có thể trở thành một phần của quy trình kiểm thử API. Thay vì chỉ kiểm tra API có trả về HTTP 200 hay không, hệ thống kiểm thử còn có thể xác nhận response có đúng cấu trúc mà API cam kết hay không.

JSON Schema kết hợp với API documentation để tạo một nguồn mô tả thống nhất

Trong một dự án chuyên nghiệp, tài liệu API không nên chỉ giải thích endpoint bằng vài ví dụ JSON. Điều quan trọng là phải xác định được request và response có cấu trúc gì, trường nào bắt buộc, kiểu dữ liệu ra sao và những giá trị nào được chấp nhận.

JSON Schema có thể đóng vai trò như một lớp mô tả cấu trúc dữ liệu trong quy trình này. Khi được kết hợp với hệ thống tài liệu API phù hợp, schema có thể giúp giảm khoảng cách giữa tài liệu và dữ liệu thực tế.

Điều này đặc biệt hữu ích khi nhiều nhóm cùng phát triển một hệ thống. Backend có thể dựa vào schema để xây dựng validation, frontend dựa vào đó để hiểu response, còn nhóm kiểm thử dùng nó để xác minh dữ liệu.

Thay vì mỗi nhóm tự viết một phiên bản mô tả riêng, một schema được quản lý tốt có thể trở thành điểm tham chiếu chung.

Những lỗi thường gặp khi xây dựng JSON Schema

Schema càng chi tiết không có nghĩa là hệ thống càng tốt. Nếu thiết kế schema thiếu cân nhắc, việc phát triển và bảo trì có thể trở nên khó khăn.

  • Quy định quá chặt: một thay đổi nhỏ trong API cũng khiến nhiều client cũ không còn tương thích.
  • Quy định quá lỏng: schema gần như không có giá trị kiểm soát vì dữ liệu sai vẫn vượt qua validation.
  • Lạm dụng required: biến mọi trường thành bắt buộc trong khi một số trường chỉ xuất hiện ở những trạng thái nhất định.
  • Không quản lý phiên bản: thay đổi schema mà không có chiến lược tương thích khiến API khó nâng cấp.
  • Nhầm validation với nghiệp vụ: đưa các quy tắc phụ thuộc database hoặc trạng thái hệ thống vào nơi không phù hợp.

Một schema tốt nên phản ánh đúng hợp đồng dữ liệu mà API thực sự cần cung cấp. Không nên biến schema thành một tập quy tắc phức tạp chỉ vì có thể biểu diễn được chúng.

Khi nào nên dùng JSON Schema và khi nào không cần quá phức tạp?

Với một đoạn JSON dùng nội bộ trong một script nhỏ, việc xây dựng schema chi tiết có thể không đem lại nhiều lợi ích. Nhưng khi dữ liệu được trao đổi giữa nhiều thành phần, đặc biệt là API công khai hoặc hệ thống có nhiều client, schema trở nên đáng giá hơn rất nhiều.

Có thể cân nhắc JSON Schema khi:

  • API có nhiều client hoặc nhiều nhóm phát triển cùng sử dụng.
  • Dữ liệu có cấu trúc phức tạp và nhiều trường lồng nhau.
  • Cần validation tự động cho request hoặc response.
  • Cần giảm lỗi khi thay đổi cấu trúc API.
  • Cần một mô tả dữ liệu có thể được công cụ xử lý.
  • Cần kiểm thử tính nhất quán của dữ liệu trong quá trình phát triển.

Ngược lại, với một JSON tạm thời chỉ dùng trong một đoạn chương trình nhỏ, việc tạo một schema đầy đủ có thể làm tăng chi phí quản lý mà không mang lại nhiều giá trị. Điều quan trọng không phải là sử dụng càng nhiều công cụ càng tốt, mà là dùng đúng công cụ ở đúng lớp của hệ thống.

JWT giải quyết bài toán truyền thông tin xác thực giữa các thành phần

JWT, viết tắt của JSON Web Token, thường xuất hiện trong các hệ thống đăng nhập và API. Tuy nhiên, JWT không phải là một cơ chế đăng nhập hoàn chỉnh. Nó là một định dạng token dùng để truyền các thông tin đã được đóng gói và ký, từ đó bên nhận có thể kiểm tra token có bị thay đổi hay không và xác định một số thông tin mà token công bố.

Điểm quan trọng cần hiểu là JWT không tự động làm cho dữ liệu bên trong trở nên bí mật. Một JWT thông thường gồm ba phần được ngăn cách bởi dấu chấm: header, payload và signature.

xxxxx.yyyyy.zzzzz

Trong đó, header mô tả loại token và thuật toán được sử dụng; payload chứa các claims; signature được tạo ra từ những phần liên quan cùng với khóa ký. Khi máy chủ nhận token, nó có thể kiểm tra chữ ký để xác định token có hợp lệ theo khóa và thuật toán mà hệ thống quy định hay không.

Ba phần của JWT có vai trò khác nhau

Header thường chứa thông tin về loại token và thuật toán ký. Một header phổ biến có dạng:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload chứa các claims. Đây là những thông tin được token mang theo, chẳng hạn mã định danh người dùng, thời điểm phát hành hoặc thời điểm hết hạn.

{
  "sub": "user_123",
  "iat": 1788600000,
  "exp": 1788603600
}

Signature là phần giúp bên nhận kiểm tra tính toàn vẹn và nguồn gốc của token theo cơ chế ký được sử dụng. Chính phần này khiến việc thay đổi payload mà không có khả năng tạo chữ ký hợp lệ trở nên dễ bị phát hiện.

Do payload thường chỉ được mã hóa theo dạng biểu diễn thuận tiện để truyền chứ không phải mã hóa bí mật, không nên đưa mật khẩu, khóa bí mật hoặc thông tin nhạy cảm vào payload với suy nghĩ rằng người khác không thể đọc được.

Claims trong JWT cần được hiểu theo mục đích thay vì chỉ xem như dữ liệu JSON

Claims là những thông tin được token mang theo. Một số claim chuẩn thường gặp gồm iss để biểu thị bên phát hành, sub để xác định chủ thể, aud để xác định đối tượng nhận, exp cho thời điểm hết hạn và iat cho thời điểm phát hành.

Ví dụ:

{
  "iss": "https://example.com",
  "sub": "user_123",
  "aud": "api",
  "iat": 1788600000,
  "exp": 1788603600
}

Những thông tin này có giá trị khi máy chủ biết mình cần kiểm tra chúng như thế nào. Chẳng hạn, việc token có trường exp không có nghĩa token tự hết hạn. Hệ thống xác thực phải thực sự kiểm tra thời gian hết hạn và từ chối token khi điều kiện không còn đáp ứng.

Tương tự, việc có claim aud không tự động đảm bảo token chỉ được sử dụng cho đúng API. Máy chủ phải kiểm tra giá trị đó theo quy tắc mà hệ thống đã thiết kế.

JWT không đồng nghĩa với mã hóa và không thay thế cơ chế phân quyền

Đây là một trong những điểm dễ gây hiểu nhầm nhất khi sử dụng JWT. Một token có chữ ký hợp lệ chỉ cho biết dữ liệu đáp ứng các điều kiện kiểm tra chữ ký và những kiểm tra bổ sung mà máy chủ thực hiện. Nó không có nghĩa người sở hữu token được phép thực hiện mọi thao tác.

Ví dụ, một token có thể xác định người dùng là user_123. Nhưng việc người dùng đó có được phép xóa sản phẩm hay không là vấn đề của authorization, không phải chỉ của việc xác thực token.

Một hệ thống có thể kiểm tra theo nhiều lớp:

  1. Token có đúng định dạng hay không.
  2. Chữ ký có hợp lệ hay không.
  3. Token đã hết hạn hay chưa.
  4. Token có được phát hành bởi nguồn tin cậy hay không.
  5. Token có đúng đối tượng sử dụng hay không.
  6. Người dùng có quyền thực hiện thao tác cụ thể hay không.

Vì vậy, JWT nên được xem là một thành phần trong kiến trúc xác thực, không phải toàn bộ hệ thống bảo mật.

JSON và XML phục vụ cùng bài toán trao đổi dữ liệu nhưng có cách tiếp cận khác nhau

XML xuất hiện trước JSON trong rất nhiều hệ thống trao đổi dữ liệu và từng đóng vai trò quan trọng trong các dịch vụ web, cấu hình phần mềm và tích hợp giữa các hệ thống doanh nghiệp. Cả XML và JSON đều có thể biểu diễn dữ liệu có cấu trúc, nhưng cách tổ chức dữ liệu của hai định dạng khác nhau đáng kể.

JSON thiên về object và array:

{
  "customer": {
    "name": "Nguyen Van A",
    "email": "a@example.com"
  }
}

Trong XML, cùng một thông tin có thể được biểu diễn bằng các element:

<customer>
  <name>Nguyen Van A</name>
  <email>a@example.com</email>
</customer>

JSON thường ngắn gọn và thuận tiện khi làm việc với JavaScript cũng như các API hiện đại. XML lại có hệ thống cú pháp và cơ chế mô tả tài liệu rất phong phú, phù hợp với những môi trường đã xây dựng trên nền XML từ lâu.

XML có lợi thế khi dữ liệu mang tính tài liệu và cần cấu trúc chặt

Một đặc điểm đáng chú ý của XML là khả năng biểu diễn không chỉ dữ liệu mà còn cấu trúc tài liệu với element, attribute và namespace. Điều này trở nên hữu ích khi nhiều hệ thống khác nhau cần trao đổi tài liệu theo một quy tắc thống nhất.

Ví dụ, XML có thể sử dụng attribute:

<product id="P1001" status="active">
  <name>San pham A</name>
</product>

Trong JSON, thông tin tương tự thường được biểu diễn như các thuộc tính của object:

{
  "product": {
    "id": "P1001",
    "status": "active",
    "name": "San pham A"
  }
}

Không nên kết luận rằng XML lỗi thời chỉ vì JSON phổ biến trong API hiện đại. Việc chọn định dạng phải dựa trên hệ thống cần tích hợp, giao thức đang sử dụng, tiêu chuẩn dữ liệu và khả năng tương thích với các phần mềm liên quan.

Khi hệ thống đang dùng XML, chuyển sang JSON chưa chắc đã là lựa chọn tốt

Một dự án có thể tồn tại nhiều năm với XML, các schema, hệ thống tích hợp và quy trình xử lý đã được xây dựng ổn định. Nếu chỉ chuyển sang JSON vì JSON ngắn hơn hoặc phổ biến hơn, chi phí thay đổi có thể lớn hơn lợi ích nhận được.

Ngược lại, với một API mới được thiết kế cho ứng dụng web hoặc mobile, JSON thường mang lại trải nghiệm thuận tiện hơn cho frontend và backend. Dữ liệu có cấu trúc gần với object và array của nhiều ngôn ngữ lập trình, đồng thời dễ đọc trong quá trình phát triển.

Vì vậy, câu hỏi đúng không phải là JSON hay XML tốt hơn? mà là định dạng nào phù hợp với hệ thống và các bên đang giao tiếp với nhau?

JSON5 mở rộng cách viết JSON để con người dễ quản lý cấu hình hơn

JSON5 được thiết kế với mục tiêu làm cho dữ liệu dạng JSON thuận tiện hơn đối với con người khi viết và chỉnh sửa. Nó bổ sung một số khả năng cú pháp quen thuộc trong JavaScript, chẳng hạn cho phép comment, sử dụng dấu nháy đơn trong một số trường hợp và cho phép dấu phẩy cuối trong object hoặc array.

Ví dụ JSON tiêu chuẩn thường viết:

{
  "name": "Web Moi",
  "version": 1
}

JSON5 có thể cho phép cách viết thuận tiện hơn:

{
  // Thong tin ung dung
  name: 'Web Moi',
  version: 1,
}

Điểm cần lưu ý là JSON5 không phải JSON chuẩn. Một parser chỉ hỗ trợ JSON tiêu chuẩn có thể không chấp nhận dữ liệu JSON5.

JSON5 phù hợp hơn với file cấu hình do con người trực tiếp chỉnh sửa

JSON thường rất phù hợp để truyền dữ liệu giữa các chương trình. Nhưng với file cấu hình mà lập trình viên phải mở ra chỉnh sửa thường xuyên, việc phải tuân thủ nghiêm ngặt mọi quy tắc của JSON đôi khi gây bất tiện.

Comment là một ví dụ điển hình. JSON tiêu chuẩn không cho phép comment, trong khi cấu hình phần mềm thường cần giải thích một tùy chọn dùng để làm gì.

{
  // So luong ket noi toi da
  maxConnections: 20,

  // Thoi gian cho tinh bang mili giay
  timeout: 5000,
}

Cách viết này dễ đọc đối với con người, nhưng hệ thống đọc file phải sử dụng parser hỗ trợ JSON5. Nếu file được gửi trực tiếp đến một API yêu cầu JSON chuẩn, JSON5 không thể được xem như một lựa chọn thay thế hoàn toàn.

Không nên dùng JSON5 cho dữ liệu API chỉ vì cú pháp dễ viết hơn

JSON5 phát huy giá trị mạnh nhất ở nơi con người thường xuyên chỉnh sửa dữ liệu. Trong giao tiếp API, yêu cầu quan trọng hơn thường là khả năng tương thích giữa nhiều hệ thống.

Nếu frontend gửi JSON5 nhưng backend chỉ chấp nhận JSON chuẩn, hệ thống sẽ phát sinh thêm một lớp chuyển đổi không cần thiết. Tương tự, nếu dữ liệu cần được trao đổi với một dịch vụ bên ngoài đã quy định JSON theo tiêu chuẩn, việc sử dụng JSON5 ở đầu giao tiếp không mang lại lợi ích đáng kể.

Có thể hình dung đơn giản:

  • JSON: phù hợp để các chương trình trao đổi dữ liệu theo cú pháp tiêu chuẩn.
  • JSON5: thuận tiện hơn khi con người trực tiếp viết hoặc duy trì dữ liệu cấu hình.
  • XML: phù hợp với nhiều hệ thống và tiêu chuẩn tích hợp dựa trên XML.
  • JWT: dùng để đóng gói thông tin claims trong một token phục vụ các cơ chế xác thực và trao đổi thông tin có ký.
  • JSON Schema: mô tả và kiểm tra cấu trúc của dữ liệu JSON.

Nhìn theo cách này, các công nghệ trên không thực sự cạnh tranh trực tiếp với nhau. Chúng nằm ở những lớp và giải quyết những nhu cầu khác nhau trong quá trình xây dựng hệ thống.

Chọn công nghệ dựa trên bài toán thay vì chạy theo định dạng phổ biến

Một hệ thống hiện đại có thể sử dụng đồng thời nhiều công nghệ. API có thể dùng JSON làm định dạng trao đổi dữ liệu, JSON Schema để kiểm tra cấu trúc, JWT cho token xác thực và vẫn phải giao tiếp với một hệ thống cũ thông qua XML.

Điều đó hoàn toàn bình thường. Việc một dự án sử dụng nhiều định dạng không nhất thiết khiến kiến trúc trở nên xấu. Vấn đề nằm ở việc mỗi định dạng có được sử dụng đúng mục đích hay không.

Ví dụ, một ứng dụng bán hàng có thể có luồng như sau:

  1. Frontend gửi request JSON đến API.
  2. API kiểm tra request theo JSON Schema.
  3. Hệ thống xác định danh tính người dùng dựa trên cơ chế token.
  4. Tầng nghiệp vụ kiểm tra quyền và dữ liệu trong cơ sở dữ liệu.
  5. API trả response JSON theo cấu trúc đã thống nhất.
  6. Nếu cần tích hợp với một hệ thống cũ, backend chuyển đổi dữ liệu sang XML ở lớp tích hợp.

Cách tổ chức này rõ ràng hơn nhiều so với việc cố sử dụng một định dạng cho tất cả mục đích.

Các công cụ xử lý JSON giúp kiểm tra và xử lý dữ liệu nhanh hơn

Khi làm việc với JSON, lập trình viên thường không chỉ cần tạo hoặc đọc dữ liệu. Trong quá trình phát triển, còn có rất nhiều công việc như kiểm tra cú pháp, định dạng lại dữ liệu, tìm lỗi trong cấu trúc, so sánh hai phiên bản JSON, chuyển đổi dữ liệu hoặc kiểm tra một response API có đúng yêu cầu hay không.

Nếu thực hiện tất cả bằng tay, đặc biệt với JSON có hàng trăm hoặc hàng nghìn dòng, khả năng bỏ sót lỗi rất cao. Các công cụ xử lý JSON giúp biến những công việc này thành các bước nhanh và có thể lặp lại.

Có thể chia nhóm công cụ theo mục đích sử dụng thay vì chỉ ghi nhớ tên từng phần mềm:

  • Formatter: làm dữ liệu dễ đọc hơn bằng cách căn lề và xuống dòng.
  • Validator: kiểm tra JSON có đúng cú pháp hay không.
  • Schema validator: kiểm tra dữ liệu có đáp ứng JSON Schema hay không.
  • Parser: chuyển JSON thành cấu trúc dữ liệu để chương trình xử lý.
  • Query tool: tìm hoặc trích xuất một phần dữ liệu từ JSON lớn.
  • Converter: chuyển đổi JSON sang định dạng khác hoặc ngược lại.
  • Diff tool: so sánh hai JSON để phát hiện phần dữ liệu thay đổi.

Formatter và validator giải quyết hai vấn đề khác nhau

Formatter chủ yếu phục vụ khả năng đọc. Một JSON viết trên một dòng có thể hoàn toàn hợp lệ nhưng rất khó kiểm tra bằng mắt:

{"user":{"id":101,"name":"Nguyen Van A","roles":["admin","editor"]}}

Sau khi format, dữ liệu trở nên dễ quan sát hơn:

{
  "user": {
    "id": 101,
    "name": "Nguyen Van A",
    "roles": [
      "admin",
      "editor"
    ]
  }
}

Validator lại trả lời một câu hỏi khác: dữ liệu này có đúng cú pháp hay không? Một formatter có thể giúp con người nhìn thấy cấu trúc, nhưng không nên xem việc format thành bằng chứng rằng dữ liệu đáp ứng mọi yêu cầu của ứng dụng.

Nếu cần kiểm tra dữ liệu theo quy tắc cụ thể, validator kết hợp với JSON Schema mới là cách tiếp cận phù hợp hơn.

Parser JSON là lớp kết nối dữ liệu với chương trình

JSON chỉ là biểu diễn dữ liệu. Để chương trình có thể làm việc với dữ liệu đó, ứng dụng cần parser hoặc thư viện hỗ trợ parse JSON thành kiểu dữ liệu mà ngôn ngữ lập trình có thể sử dụng.

Trong PHP, việc giải mã JSON thường được thực hiện bằng json_decode(). Ví dụ:

<?php

$json = '{"name":"Nguyen Van A","age":30}';

$data = json_decode($json, true);

echo $data['name'];

Tham số thứ hai trong ví dụ trên yêu cầu PHP chuyển object JSON thành associative array. Nếu không truyền tham số này, object JSON thường được chuyển thành object tương ứng của PHP.

Chiều ngược lại có thể sử dụng json_encode():

<?php

$data = [
    'name' => 'Nguyen Van A',
    'age' => 30
];

echo json_encode($data);

Đây là hai thao tác cơ bản nhưng xuất hiện rất thường xuyên trong API PHP: nhận JSON từ client để xử lý và chuyển dữ liệu PHP thành JSON để trả về.

Không nên xem json_decode là bước kiểm tra toàn bộ dữ liệu

Việc json_decode() thành công chỉ cho biết chuỗi đã được phân tích thành cấu trúc dữ liệu hợp lệ theo parser. Nó không đảm bảo dữ liệu đáp ứng yêu cầu nghiệp vụ.

Ví dụ JSON sau hoàn toàn có thể hợp lệ:

{
  "quantity": -10
}

Nhưng nếu số lượng sản phẩm phải lớn hơn 0 thì đây vẫn là dữ liệu không hợp lệ đối với ứng dụng.

Do đó, sau khi parse JSON, ứng dụng vẫn cần kiểm tra các trường bắt buộc, kiểu dữ liệu, giới hạn giá trị, quyền truy cập và các quy tắc nghiệp vụ cần thiết.

Xử lý lỗi JSON cần được thiết kế rõ thay vì để ứng dụng tự thất bại

Trong một API thực tế, JSON đầu vào có thể bị lỗi do client gửi sai cú pháp, request bị cắt giữa chừng hoặc dữ liệu được tạo bởi một phần mềm không tuân thủ đúng hợp đồng API.

Ứng dụng nên phát hiện lỗi và trả về phản hồi có ý nghĩa thay vì tiếp tục xử lý dữ liệu không hợp lệ.

<?php

$json = '{"name":"Nguyen Van A",}';

$data = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    echo 'JSON khong hop le';
}

Trong những phiên bản PHP phù hợp, có thể sử dụng cách xử lý lỗi dựa trên exception để luồng chương trình rõ ràng hơn:

<?php

try {
    $data = json_decode(
        $json,
        true,
        512,
        JSON_THROW_ON_ERROR
    );
} catch (JsonException $e) {
    echo 'Khong the xu ly JSON';
}

Điểm quan trọng không nằm ở việc chọn cách nào, mà là phải có một chiến lược xử lý lỗi thống nhất. API nên phân biệt được request JSON bị lỗi cú pháp với request có JSON hợp lệ nhưng vi phạm quy tắc dữ liệu.

JSON lớn cần được xử lý khác với một response nhỏ

Với một JSON vài kilobyte, việc đọc toàn bộ dữ liệu vào bộ nhớ thường không phải vấn đề. Nhưng khi dữ liệu tăng lên hàng chục, hàng trăm megabyte hoặc lớn hơn, cách xử lý toàn bộ tài liệu cùng lúc có thể gây áp lực đáng kể lên bộ nhớ.

Đây là lúc cần cân nhắc các phương pháp xử lý theo luồng, parser streaming hoặc chia nhỏ dữ liệu ngay từ nguồn.

Ví dụ, nếu API phải trả về hàng trăm nghìn sản phẩm, việc tạo một JSON khổng lồ cho một request duy nhất thường không phải thiết kế tối ưu. Phân trang sẽ hợp lý hơn:

{
  "page": 1,
  "per_page": 50,
  "total": 125000,
  "items": [
    {
      "id": 1,
      "name": "San pham A"
    }
  ]
}

Cách này không chỉ giảm kích thước response mà còn giảm lượng dữ liệu phải parse, truyền qua mạng và lưu trong bộ nhớ ở mỗi phía.

Công cụ query JSON hữu ích khi dữ liệu đã quá lớn để tìm thủ công

Khi cần tìm một trường trong JSON nhỏ, việc mở file và tìm kiếm bằng trình soạn thảo là đủ. Nhưng với dữ liệu phức tạp, có nhiều object lồng nhau hoặc hàng nghìn phần tử, công cụ query JSON có thể giúp lấy đúng phần cần thiết mà không phải đọc toàn bộ dữ liệu bằng mắt.

Ví dụ, với dữ liệu:

{
  "orders": [
    {
      "id": 1001,
      "customer": "A",
      "total": 500000
    },
    {
      "id": 1002,
      "customer": "B",
      "total": 850000
    }
  ]
}

Người xử lý dữ liệu có thể cần lấy riêng danh sách mã đơn hàng, lọc các đơn có tổng tiền vượt một mức nhất định hoặc trích xuất tên khách hàng. Các công cụ truy vấn JSON cho phép thực hiện những thao tác như vậy mà không cần viết một chương trình hoàn chỉnh cho từng lần kiểm tra.

Những công cụ dòng lệnh chuyên xử lý JSON cũng đặc biệt hữu ích trong môi trường server, CI/CD và các script tự động hóa. Chúng có thể nhận JSON từ API, lọc dữ liệu, biến đổi cấu trúc rồi chuyển kết quả sang bước xử lý tiếp theo.

So sánh JSON bằng diff giúp phát hiện thay đổi API nhanh hơn

Hai JSON có thể chứa gần như cùng một dữ liệu nhưng được sắp xếp hoặc xuống dòng khác nhau. Nếu so sánh trực tiếp bằng văn bản, người phát triển có thể mất thời gian phân biệt đâu là thay đổi thực sự và đâu chỉ là thay đổi về định dạng.

JSON diff xử lý vấn đề này bằng cách phân tích cấu trúc dữ liệu rồi chỉ ra những thuộc tính được thêm, xóa hoặc thay đổi.

Ví dụ phiên bản đầu tiên:

{
  "id": 1001,
  "name": "San pham A",
  "price": 500000
}

Phiên bản sau:

{
  "id": 1001,
  "name": "San pham A",
  "price": 550000,
  "stock": 20
}

Điểm đáng quan tâm ở đây không phải toàn bộ tài liệu đã thay đổi mà là price được cập nhật và stock được thêm vào. Cách so sánh theo cấu trúc đặc biệt hữu ích khi kiểm tra thay đổi response API hoặc dữ liệu cấu hình.

Chuyển đổi giữa JSON, XML và các định dạng khác cần giữ nguyên ý nghĩa dữ liệu

Công cụ chuyển đổi định dạng có thể biến JSON thành XML hoặc XML thành JSON khá nhanh, nhưng không nên xem đây là thao tác chỉ thay đổi cú pháp.

Hai định dạng có cách biểu diễn dữ liệu khác nhau. XML có element, attribute và namespace; JSON có object, array và các kiểu giá trị riêng. Khi chuyển đổi, một số thông tin có thể không có ánh xạ trực tiếp hoặc phải được biểu diễn theo quy ước riêng.

Ví dụ XML:

<product id="P1001">
  <name>San pham A</name>
</product>

Có thể được biểu diễn trong JSON theo một quy ước:

{
  "product": {
    "@id": "P1001",
    "name": "San pham A"
  }
}

Dấu @ trong ví dụ trên không phải cú pháp đặc biệt của JSON. Nó chỉ là một quy ước do một công cụ hoặc hệ thống chuyển đổi lựa chọn để phân biệt attribute với element.

Vì vậy, khi chuyển đổi giữa hai định dạng, cần xác định rõ quy tắc ánh xạ thay vì chỉ kiểm tra xem kết quả có đúng cú pháp hay không.

JSON Schema, JWT và JSON5 không nên bị gom thành một nhóm công nghệ

Dù đều liên quan đến JSON, ba công nghệ này giải quyết ba vấn đề hoàn toàn khác nhau.

Công nghệ Vai trò chính Vấn đề giải quyết
JSON Schema Mô tả và xác thực dữ liệu Dữ liệu có đúng cấu trúc và các ràng buộc đã định nghĩa hay không
JWT Đóng gói claims trong token có chữ ký Truyền thông tin phục vụ các cơ chế xác thực và trao đổi claims
JSON5 Mở rộng cú pháp viết JSON Làm dữ liệu cấu hình dễ viết và dễ đọc hơn đối với con người
XML Định dạng dữ liệu và tài liệu có cấu trúc Trao đổi dữ liệu trong các hệ thống sử dụng XML và các tiêu chuẩn liên quan

Việc phân biệt vai trò giúp tránh những quyết định kiến trúc sai. JSON Schema không phải cơ chế xác thực người dùng. JWT không phải validator JSON. JSON5 cũng không phải phiên bản JSON dùng trực tiếp cho mọi API.

Một quy trình xử lý JSON tốt cần phân tách từng lớp trách nhiệm

Trong một ứng dụng thực tế, xử lý JSON nên được tổ chức thành nhiều bước thay vì gom tất cả vào một đoạn code.

  1. Nhận dữ liệu: lấy JSON từ request, file hoặc dịch vụ bên ngoài.
  2. Kiểm tra cú pháp: xác định dữ liệu có thể parse hay không.
  3. Validation: kiểm tra cấu trúc bằng JSON Schema hoặc cơ chế tương đương.
  4. Kiểm tra nghiệp vụ: xác minh dữ liệu có phù hợp với trạng thái thực tế của hệ thống.
  5. Authorization: xác định người gọi có quyền thực hiện hành động hay không.
  6. Xử lý: thực hiện nghiệp vụ sau khi dữ liệu đã vượt qua các lớp kiểm tra cần thiết.
  7. Đóng gói response: trả về JSON theo cấu trúc API đã công bố.
  8. Kiểm thử: xác nhận response và các trường hợp lỗi vẫn đáp ứng hợp đồng dữ liệu.

Cách phân lớp này giúp lỗi dễ xác định hơn. Nếu request không parse được, lỗi nằm ở dữ liệu đầu vào. Nếu parse được nhưng không vượt qua schema, lỗi nằm ở cấu trúc. Nếu schema hợp lệ nhưng không được phép thực hiện thao tác, đó là vấn đề authorization hoặc nghiệp vụ.

JSON nâng cao nên được học theo vấn đề thay vì học thuộc từng công cụ

Điểm quan trọng nhất khi làm việc chuyên sâu với JSON không phải là ghi nhớ thật nhiều công cụ. Điều quan trọng là hiểu dữ liệu đang cần giải quyết vấn đề gì.

Nếu vấn đề là dữ liệu có cấu trúc không thống nhất, hãy nghĩ đến JSON Schema. Nếu vấn đề là truyền claims trong một token có chữ ký, JWT có thể là một thành phần phù hợp. Nếu cần duy trì file cấu hình dễ đọc và dễ chỉnh sửa, JSON5 có thể đáng cân nhắc. Nếu phải tích hợp với hệ thống doanh nghiệp hoặc nền tảng đã dựa trên XML, XML vẫn có thể là lựa chọn đúng.

Còn nếu vấn đề là kiểm tra, định dạng, truy vấn hoặc chuyển đổi dữ liệu, hãy chọn công cụ xử lý JSON phù hợp với quy mô và môi trường làm việc thay vì thao tác thủ công.

Đối với một website hoặc hệ thống web được xây dựng bài bản, những kiến thức này đặc biệt hữu ích khi API bắt đầu có nhiều client, dữ liệu ngày càng phức tạp và yêu cầu tích hợp ngày càng cao. JSON lúc đó không còn đơn thuần là một chuỗi dữ liệu được encode và decode, mà trở thành một phần của hợp đồng giữa các thành phần trong toàn bộ hệ thống.

Với Web Mới, việc hiểu sâu cách tổ chức và xử lý dữ liệu cũng là nền tảng quan trọng khi xây dựng website, API và các hệ thống web theo yêu cầu. Khi dữ liệu được thiết kế rõ ràng ngay từ đầu, việc mở rộng tính năng, tích hợp dịch vụ và bảo trì hệ thống về sau sẽ thuận lợi hơn rất nhiều.

Cuối cùng, nên nhìn JSON như một phần của kiến trúc dữ liệu thay vì một định dạng độc lập. JSON Schema giúp đặt ra hợp đồng dữ liệu, JWT phục vụ một lớp xác thực và trao đổi claims, XML duy trì khả năng tương tác với những hệ thống phù hợp, JSON5 giải quyết nhu cầu viết cấu hình thuận tiện hơn, còn các công cụ xử lý JSON giúp kiểm tra và biến đổi dữ liệu trong suốt vòng đời của ứng dụng.

  • 0 Bình luận
CEO Bùi Tấn Lực | Founder Web Mới
Bùi Tấn Lực
Tìm hiểu về CEO Bùi Tấn Lực, Founder Web Mới với nhiều năm kinh nghiệm trong lĩnh vực phát triển website, SEO và chia sẻ kiến thức công nghệ
Đánh giá
Chia sẻ nội dung đánh giá của bạn về JSON nâng cao: JSON Schema, JWT, XML, JSON5 và các công cụ xử lý JSON
Email, Điện thoại của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *
Đánh giá của bạn
Tên *
Email
Số điện thoại *
Bình luận, Hỏi đáp
Yêu Cầu Báo Giá
Gửi trang web mẫu cần làm theo, chúng tôi sẽ báo giá đến bạn từ Email (tanlucit09@gmail.com - Bùi Tấn Lực) hoặc Zalo (Lực IT - 0398259259) !