Tuần siêu khuyến mãiClaude Skills — GIẢM 20%
Glossary

Làm chủ các tệp JSONL: Cấu trúc, Trường hợp Sử dụng và Những Ưu điểm Chính

Powerdrill Bloom·
Làm chủ các tệp JSONL: Cấu trúc, Trường hợp Sử dụng và Những Ưu điểm Chính

Một tệp JSONL chứa một giá trị JSON hoàn chỉnh trên mỗi dòng. Tài liệu chính thức gọi định dạng này là "định dạng văn bản JSON Lines, còn được gọi là JSON phân tách bằng dòng mới". Quy tắc duy nhất đó là lý do tại sao nó truyền luồng tốt, tại sao nó vẫn hoạt động khi chỉ đọc được một phần, và tại sao một bảng tính sẽ không thể mở được nó.

Tệp JSONL là gì?

JSON Lines là một định dạng văn bản dành cho các bản ghi. Tài liệu đặc tả mô tả nó là "một định dạng thuận tiện để lưu trữ dữ liệu có cấu trúc có thể được xử lý từng bản ghi một tại một thời điểm".

Tài liệu hướng dẫn nêu rất rõ về phạm vi áp dụng của nó. Nó "hoạt động tốt với các công cụ xử lý văn bản kiểu unix và các đường ống shell (shell pipeline)", và trang này bổ sung thêm rằng "đây là một định dạng tuyệt vời cho các tệp nhật ký (log file)". Nó cũng được mô tả là "một định dạng linh hoạt để truyền thông điệp giữa các tiến trình hợp tác với nhau".

Sự khác biệt so với JSON thông thường chính là điểm mấu chốt. Một mảng JSON gồm một triệu bản ghi là một giá trị duy nhất: trình đọc phải tải toàn bộ mảng đó trước khi cấu trúc hoàn tất. Trong khi đó, một tệp JSONL gồm một triệu bản ghi là một triệu giá trị, và mỗi dòng hoạt động hoàn toàn độc lập.

Có một đặc tả thứ hai liên quan chặt chẽ đến nó. Đặc tả NDJSON nói thẳng về điều này: "hiện tại không có tiêu chuẩn nào cho việc truyền tải các thực thể văn bản JSON trong một giao thức truyền luồng". Trường hợp sử dụng được nêu ra của nó là "truyền tải nhiều thực thể văn bản JSON thông qua các giao thức truyền luồng như TCP hoặc UNIX Pipes".

Cấu trúc của một tệp JSONL

Ba yêu cầu bắt buộc

Tài liệu JSON Lines liệt kê chính xác ba yêu cầu. Đầu tiên là mã hóa UTF-8. Nó đi kèm với một lưu ý được mượn từ chính tiêu chuẩn JSON: "giống như tiêu chuẩn JSON, ký tự đánh dấu thứ tự byte (BOM - U+FEFF) KHÔNG được đưa vào".

Thứ hai là mỗi dòng phải là một giá trị JSON hợp lệ. Trang tài liệu lưu ý rằng "các giá trị phổ biến nhất sẽ là các đối tượng (object) hoặc mảng (array), nhưng bất kỳ giá trị JSON nào cũng được phép". Sau đó, nó đưa ra một trường hợp đặc biệt dễ gây nhầm lẫn: "null là một giá trị hợp lệ nhưng một dòng trống thì không".

Thứ ba là ký tự kết thúc dòng là \n. Các ký tự kết thúc dòng của Windows vẫn hoạt động. Lý do được đưa ra mang tính kỹ thuật: "điều này có nghĩa là \r\n cũng được hỗ trợ vì khoảng trắng xung quanh được bỏ qua một cách ngầm định khi phân tích cú pháp các giá trị JSON".

Những gì không được xuất hiện trong một dòng

Đây là ràng buộc giúp định dạng này hoạt động hiệu quả. Đặc tả NDJSON nêu rõ đây là một yêu cầu bắt buộc: "các văn bản JSON KHÔNG ĐƯỢC chứa ký tự xuống dòng hoặc ký tự về đầu dòng".

Một giá trị JSON thông thường được phép trải dài trên nhiều dòng với các khoảng lùi đầu dòng. Nhưng trong một tệp phân tách bằng dòng, điều này là không thể, bởi vì ký tự xuống dòng chính là ký tự phân tách các bản ghi. Mỗi bản ghi phải được viết trên một dòng vật lý duy nhất.

Dòng cuối cùng và các dòng trống

Có hai chi tiết khác biệt giữa hai đặc tả này, và cả hai đều quan trọng khi một tệp bị từ chối.

Hãy xem xét ký tự xuống dòng ở cuối tệp. JSON Lines nói rằng "việc bao gồm một ký tự kết thúc dòng sau giá trị JSON cuối cùng trong tệp rất được khuyến khích nhưng không bắt buộc".

Về các dòng trống, hai đặc tả này không thống nhất với nhau. JSON Lines rất nghiêm ngặt: một dòng trống không phải là một giá trị hợp lệ. NDJSON thì dễ dãi hơn, cho phép "trình phân tích cú pháp CÓ THỂ âm thầm bỏ qua các dòng trống", đồng thời yêu cầu "hành vi này PHẢI được ghi chép lại trong tài liệu".

Phần mở rộng và loại phương tiện (media type)

Cách đặt tên cũng có sự phân chia. JSON Lines nói rằng các tệp "có thể được lưu với phần mở rộng tệp là .jsonl". Về loại phương tiện, tài liệu này cho biết "loại MIME có thể là application/jsonl, nhưng điều này vẫn chưa được tiêu chuẩn hóa". NDJSON thì cho rằng loại phương tiện "NÊN là application/x-ndjson" và phần mở rộng "NÊN là .ndjson".

Đối với việc nén dữ liệu, JSON Lines khuyên dùng các trình nén luồng: "gzip hoặc bzip2 được khuyên dùng để tiết kiệm dung lượng, tạo ra các tệp .jsonl.gz hoặc .jsonl.bz2".

Có một quy ước nhỏ đáng lưu ý khi bạn đọc thông báo lỗi. Các trình soạn thảo văn bản gọi dòng đầu tiên là "dòng 1". Tài liệu hướng dẫn mở rộng điều đó: "giá trị đầu tiên trong tệp JSON Lines cũng nên được gọi là 'giá trị 1'".

JSONL được dùng để làm gì

Bạn thường sẽ gặp tệp .jsonl trong một trong bốn tình huống sau.

Các tệp nhật ký (log) và sự kiện. Tài liệu của chính định dạng này đề cập đến các tệp nhật ký, và lý do là vì trình ghi có thể thêm từng dòng một vào cuối tệp mà không cần phải ghi lại bất kỳ nội dung nào trước đó.

Tải dữ liệu vào kho lưu trữ (warehouse). Tài liệu BigQuery của Google là một ví dụ điển hình cho vị thế chính thức của định dạng này. Nó hỗ trợ tải "dữ liệu JSON phân tách bằng dòng mới (ndJSON) từ Cloud Storage", và trình chọn định dạng tệp của nó liệt kê tùy chọn này là "JSONL (Newline delimited JSON)".

Xuất dữ liệu API của các bản ghi lồng nhau. Dữ liệu không thể chuyển đổi phẳng một cách gọn gàng thành các cột sẽ giữ nguyên cấu trúc lồng nhau của nó trên mỗi dòng. Các dòng đơn hàng với số lượng mặt hàng thay đổi là một trường hợp điển hình.

Các tập dữ liệu học máy (machine learning). Các tập dữ liệu huấn luyện và đánh giá thường được phân phối theo cách này, vì một vòng lặp huấn luyện sẽ đọc các bản ghi từng bản ghi một.

Điểm chung ở đây là việc truyền luồng (streaming). Nó trở thành lựa chọn hiển nhiên khi tệp được tạo ra dần dần hoặc được sử dụng dần dần.

JSONL so với JSON so với CSV

JSONL JSON CSV
Đơn vị của tệp Một giá trị trên mỗi dòng Một giá trị cho toàn bộ tệp Một hàng trên mỗi dòng
Dữ liệu lồng nhau Có, trên mỗi bản ghi Không hỗ trợ gốc
Thêm một bản ghi vào cuối Thêm một dòng Ghi lại toàn bộ khung chứa Thêm một hàng
Đọc một phần có hữu ích không Hiếm khi
Mở được trong bảng tính Không Không Thường là có
Các bản ghi có thể khác nhau về cấu trúc Không, các cột là cố định
Con người có thể đọc được trong trình soạn thảo Có, mỗi bản ghi là một dòng dài Có, khi được thụt lề

Hàng gây ngạc nhiên nhất là hàng áp chót. Hai dòng trong cùng một tệp JSONL có thể chứa các khóa (key) khác nhau. Đó chính xác là điều làm cho định dạng này trở nên linh hoạt, và cũng chính xác là lý do tại sao việc nhập dữ liệu một cách đơn giản sẽ tạo ra các cột không đồng đều.

Đối với giải pháp thay thế dạng nhị phân hướng cột, bài giải thích về Parquet sẽ đề cập đến cùng một phạm vi từ khía cạnh lưu trữ. Đối với trường hợp bảng đơn giản nhất, bài phân tích về TSV sẽ nói về văn bản được phân tách bằng tab.

Các ưu điểm chính

Chỉ ghi thêm vào cuối (Append-only). Một bản ghi mới là một dòng mới. Không có gì trước đó trong tệp cần phải thay đổi.

Đọc dạng luồng (Streaming). Bên sử dụng dữ liệu có thể xử lý bản ghi số một trước khi bản ghi thứ hai triệu được ghi vào.

Khả năng chịu lỗi. Một tệp bị cắt ngắn vẫn có thể đọc được cho đến dòng hoàn chỉnh cuối cùng. Trong khi đó, một mảng JSON bị cắt ngắn thường hoàn toàn không thể đọc được.

Giữ nguyên cấu trúc lồng nhau. Cấu trúc mà CSV buộc phải chuyển đổi phẳng vẫn được giữ nguyên vẹn bên trong mỗi bản ghi.

Thân thiện với Shell. Tài liệu hướng dẫn đánh giá cao khả năng xử lý văn bản kiểu unix và các đường ống shell, bởi vì một tệp hướng dòng sẽ hoạt động tốt với các công cụ hướng dòng.

Hỗ trợ kho lưu trữ dữ liệu. Tài liệu của BigQuery nêu rõ quy tắc mà nó áp dụng: "mỗi đối tượng JSON phải nằm trên một dòng riêng biệt trong tệp".

Những hạn chế của JSONL

Định dạng này giải quyết vấn đề truyền tải và ghi thêm dữ liệu. Nó không giải quyết bất kỳ câu hỏi nào của bạn về nội dung bên trong.

Nén dữ liệu là một sự đánh đổi thực sự chứ không phải là một lợi ích miễn phí. Tài liệu của BigQuery nói thẳng về chi phí này: "nếu bạn sử dụng nén gzip, BigQuery không thể đọc dữ liệu song song". Tài liệu này bổ sung thêm rằng "việc tải dữ liệu JSON đã nén vào BigQuery sẽ chậm hơn so với tải dữ liệu chưa nén". Trang riêng của định dạng này lại khuyên dùng gzip để tiết kiệm dung lượng. Cả hai điều này đều đúng, và chúng đi theo hai hướng ngược nhau.

Nó cũng rất dài dòng. Mỗi dòng đều lặp lại mọi tên khóa (key), vì vậy một tập hợp bản ghi rộng sẽ lớn hơn đáng kể so với cùng một dữ liệu đó ở định dạng cột.

Và nó không nói lên điều gì về tính nhất quán. Các bản ghi có cấu trúc khác nhau được phép tồn tại, điều đó có nghĩa là một trường dữ liệu có thể âm thầm ngừng xuất hiện ở giữa tệp mà không làm cho tệp bị coi là không hợp lệ.

Cách làm việc với tệp JSONL nếu bạn không phải là kỹ sư

Đây là khoảng cách thực tế. Các công cụ kinh doanh thường yêu cầu các hàng và cột, và một tệp .jsonl sẽ không thể mở được theo cách của một tệp CSV.

Giải pháp thực tế là thực hiện một bước chuyển đổi. Hãy yêu cầu người tạo ra tệp cung cấp một bản trích xuất CSV hoặc Excel đã được làm phẳng chứa các trường bạn cần. Hoặc bạn có thể tự làm phẳng nó bằng bất kỳ công cụ nào hỗ trợ JSON. Bạn sẽ mất đi cấu trúc lồng nhau, nhưng điều này thường không quan trọng một khi bạn đã quyết định sử dụng các trường nào cho việc phân tích.

Từ đó, công việc chỉ là phân tích thông thường. Trang bảng giá của Powerdrill Bloom liệt kê các tệp tải lên cho Excel, CSV, PDF và các tài liệu khác, vì vậy một bản trích xuất đã làm phẳng có thể được đưa thẳng vào. Các câu hỏi được đặt bằng ngôn ngữ tự nhiên thay vì phải viết dưới dạng các câu truy vấn. Trợ lý AI cho CSV hỗ trợ lộ trình đó, và các cổng kết nối dữ liệu sẽ giải quyết các trường hợp mà dữ liệu được lấy trực tiếp từ nguồn tốt hơn là xuất ra tệp.

Điểm khác biệt đáng lưu ý là đây là một quyết định truyền tải được đưa ra từ phía thượng nguồn trước khi đến tay bạn. Việc chuyển đổi nó sang định dạng khác khi tệp đến bàn làm việc của bạn là điều bình thường, chứ không phải là một giải pháp tạm thời.

Kết luận

JSONL là một định dạng văn bản với một quy tắc duy nhất: một giá trị JSON hoàn chỉnh trên mỗi dòng, và không có ký tự xuống dòng bên trong một giá trị. Quy tắc đó mang lại khả năng ghi thêm, truyền luồng và khả năng chịu lỗi khi đọc một phần, đó là lý do tại sao các tệp nhật ký và việc tải dữ liệu vào kho lưu trữ mặc định sử dụng nó.

Những gì nó không mang lại là một bảng dữ liệu. Ngay khi tệp đến tay một người cần câu trả lời thay vì một đường ống dữ liệu, bước tiếp theo hữu ích là một bản trích xuất đã được làm phẳng và một câu hỏi.

Nếu đó là tình huống của bạn, hãy thử Powerdrill Bloom với tệp đã được chuyển đổi và bắt đầu bằng việc biến nó thành một biểu đồ.

Các câu hỏi thường gặp

Tệp JSONL được dùng để làm gì?

Nó được sử dụng cho các luồng bản ghi: tệp nhật ký, xuất sự kiện, tải dữ liệu vào kho lưu trữ và các tập dữ liệu học máy. Tài liệu của định dạng này đề cập cụ thể đến các tệp nhật ký và các đường ống shell. Điểm chung là các bản ghi được ghi hoặc đọc từng bản ghi một tại một thời điểm.

Sự khác biệt giữa JSONL và NDJSON là gì?

Chúng mô tả cùng một ý tưởng với các thủ tục giấy tờ khác nhau. JSON Lines sử dụng phần mở rộng .jsonl và lưu ý rằng application/jsonl vẫn chưa được tiêu chuẩn hóa. NDJSON chỉ định .ndjsonapplication/x-ndjson, đồng thời nó cho phép các trình phân tích cú pháp bỏ qua các dòng trống.

Tôi có thể mở tệp JSONL trong Excel?

Không thể mở bằng cách nhấp đúp vào nó, bởi vì mỗi dòng là một giá trị JSON chứ không phải là một hàng gồm các ô dữ liệu. Cách tiếp cận thông thường là làm phẳng các trường bạn cần thành CSV hoặc Excel trước, hoặc sử dụng một công cụ đọc trực tiếp định dạng này.

Tại sao một bản ghi không thể trải dài trên nhiều dòng trong JSONL?

Bởi vì ký tự xuống dòng chính là ký tự phân tách các bản ghi. Đặc tả NDJSON nêu rõ rằng "các văn bản JSON KHÔNG ĐƯỢC chứa ký tự xuống dòng hoặc ký tự về đầu dòng". Do đó, JSON được định dạng đẹp (pretty-printed) phải được thu gọn lại thành một dòng duy nhất cho mỗi bản ghi.

Dòng trống có được phép xuất hiện trong tệp JSONL không?

Hai đặc tả này có sự khác biệt. JSON Lines tuyên bố rằng "null là một giá trị hợp lệ nhưng một dòng trống thì không". NDJSON cho phép trình phân tích cú pháp âm thầm bỏ qua các dòng trống, miễn là hành vi đó được ghi chép lại trong tài liệu.