JSON, hoặc Ký hiệu đối tượng JavaScript, ở xung quanh chúng ta. Nếu bạn đã từng sử dụng một ứng dụng web, thì rất có thể ứng dụng đó đã sử dụng JSON để cấu trúc, lưu trữ và truyền dữ liệu giữa các máy chủ của nó và thiết bị của bạn.
Trong bài viết này, chúng ta sẽ tìm hiểu ngắn gọn về sự khác biệt giữa JSON và JavaScript, sau đó chuyển sang các cách khác nhau để phân tích cú pháp JSON bằng JavaScript trong trình duyệt và trong các dự án Node.js.
Sự khác biệt giữa JSON và JavaScript
Mặc dù JSON trông giống như JavaScript thông thường, nhưng tốt hơn hết bạn nên coi JSON là định dạng dữ liệu, tương tự như tệp văn bản. Thực tế là JSON được lấy cảm hứng từ cú pháp JavaScript, đó là lý do tại sao chúng trông rất giống nhau.
Chúng ta hãy xem xét các đối tượng JSON và mảng JSON và so sánh chúng với các đối tượng JavaScript của chúng.
Các đối tượng JSON so với các đối tượng JavaScript
Đầu tiên, đây là một đối tượng JSON:
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
}
Sự khác biệt chính giữa đối tượng JSON và đối tượng JavaScript thông thường – còn được gọi là đối tượng theo nghĩa đen – nằm ở dấu ngoặc kép. Tất cả các khóa và giá trị kiểu chuỗi trong đối tượng JSON phải được đặt trong dấu ngoặc kép ("
).
Đối tượng chữ JavaScript linh hoạt hơn một chút. Với các ký tự đối tượng, bạn không cần đặt khóa và chuỗi trong dấu ngoặc kép. Thay vào đó, bạn có thể sử dụng dấu nháy đơn ('
) hoặc không sử dụng bất kỳ loại dấu ngoặc kép nào cho các phím.
Đây là đoạn mã trên có thể trông giống như một đối tượng JavaScript theo nghĩa đen:
const profile = {
name: 'Jane Doe',
'favorite-game': 'Stardew Valley',
subscriber: false
}
Lưu ý rằng chìa khóa 'favorite-game'
được bao bọc trong dấu nháy đơn. Với các ký tự đối tượng, bạn sẽ cần ngắt các phím trong đó các từ được phân tách bằng dấu gạch ngang (-
) trích dẫn.
Nếu bạn muốn tránh dấu ngoặc kép, bạn có thể viết lại khóa để sử dụng trường hợp lạc đà (favoriteGame
) hoặc tách các từ bằng dấu gạch dưới (favorite_game
) thay thế.
Mảng JSON so với mảng JavaScript
Các mảng JSON hoạt động khá giống với các mảng trong JavaScript và có thể chứa các chuỗi, boolean, số và các đối tượng JSON khác. Ví dụ:
[
{
"name": "Jane Doe",
"favorite-game": "Stardew Valley",
"subscriber": false
},
{
"name": "John Doe",
"favorite-game": "Dragon Quest XI",
"subscriber": true
}
]
Đây là những gì có thể trông giống như trong JavaScript đơn giản:
const profiles = [
{
name: 'Jane Doe',
'favorite-game': 'Stardew Valley',
subscriber: false
},
{
name: 'John Doe',
'favorite-game': 'Dragon Quest XI',
subscriber: true
}
];
JSON dưới dạng chuỗi
Bạn có thể tự hỏi, nếu có các đối tượng và mảng JSON, bạn không thể sử dụng nó trong chương trình của mình như một mảng hoặc đối tượng JavaScript thông thường sao?
Lý do tại sao bạn không thể làm điều này là JSON thực sự chỉ là một chuỗi.
Ví dụ: khi bạn viết JSON trong một tệp riêng biệt như với jane-profile.json
hoặc profiles.json
ở trên, tệp đó thực sự chứa văn bản ở dạng đối tượng hoặc mảng JSON, trông giống như JavaScript.
Và nếu bạn yêu cầu một API, nó sẽ trả về một cái gì đó như thế này:
{"name":"Jane Doe","favorite-game":"Stardew Valley","subscriber":false}
Cũng giống như với các tệp văn bản, nếu bạn muốn sử dụng JSON trong dự án của mình, bạn sẽ cần phân tích cú pháp hoặc thay đổi nó thành thứ mà ngôn ngữ lập trình của bạn có thể hiểu được. Chẳng hạn, phân tích cú pháp một đối tượng JSON trong Python sẽ tạo ra một từ điển.
Với sự hiểu biết đó, chúng ta hãy xem xét các cách khác nhau để phân tích cú pháp JSON trong JavaScript.
Cách phân tích cú pháp JSON trong trình duyệt
Nếu bạn đang làm việc với JSON trong trình duyệt, thì có thể bạn đang nhận hoặc gửi dữ liệu thông qua một API.
Chúng ta hãy xem một vài ví dụ.
Cách phân tích cú pháp JSON bằng fetch
Cách dễ nhất để lấy dữ liệu từ API là với fetch
trong đó bao gồm .json()
phương pháp để phân tích các phản hồi JSON thành một đối tượng JavaScript có thể sử dụng được theo nghĩa đen hoặc mảng một cách tự động.
Đây là một số mã sử dụng fetch
để làm một GET
yêu cầu trò đùa theo chủ đề nhà phát triển từ API Truyện cười Chuck Norris miễn phí:
fetch('https://api.chucknorris.io/jokes/random?category=dev')
.then(res => res.json()) // the .json() method parses the JSON response into a JS object literal
.then(data => console.log(data));
Nếu bạn chạy mã đó trong trình duyệt, bạn sẽ thấy nội dung như thế này được ghi vào bảng điều khiển:
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
}
Mặc dù nó trông giống như một đối tượng JSON, nhưng nó thực sự là một đối tượng JavaScript theo nghĩa đen và bạn có thể sử dụng nó một cách tự do trong chương trình của mình.
Cách xâu chuỗi JSON với JSON.stringify()
Nhưng nếu bạn muốn gửi dữ liệu tới một API thì sao?
Ví dụ: giả sử bạn muốn gửi một câu chuyện cười Chuck Norris tới API Truyện cười Chuck Norris để những người khác có thể đọc nó sau.
Đầu tiên, bạn sẽ viết trò đùa của mình dưới dạng đối tượng JS theo nghĩa đen:
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
Sau đó, vì bạn đang gửi dữ liệu tới một API, nên bạn cần chuyển newJoke
đối tượng bằng chữ thành một chuỗi JSON.
May mắn thay, JavaScript bao gồm một phương thức siêu hữu ích để làm việc đó – JSON.stringify()
:
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
console.log(JSON.stringify(newJoke)); // {"categories":["dev"],"value":"Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."}
console.log(typeof JSON.stringify(newJoke)); // string
Trong khi chúng tôi đang chuyển đổi một đối tượng bằng chữ thành một chuỗi JSON trong ví dụ này, JSON.stringify()
cũng hoạt động với mảng.
Cuối cùng, bạn chỉ cần gửi trò đùa được xâu chuỗi JSON của mình trở lại API bằng một POST
yêu cầu.
Lưu ý rằng API Truyện cười Chuck Norris không thực sự có tính năng này. Nhưng nếu đúng như vậy, đây là mã có thể trông như thế nào:
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
fetch('https://api.chucknorris.io/jokes/submit', { // fake API endpoint
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newJoke), // turn the JS object literal into a JSON string
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => {
console.error(err);
});
Và cứ như vậy, bạn đã phân tích cú pháp JSON đến bằng fetch
và sử dụng JSON.stringify()
để chuyển đổi một đối tượng JS theo nghĩa đen thành một chuỗi JSON.
Cách làm việc với các tệp JSON cục bộ trong trình duyệt
Thật không may, không thể (hoặc nên) tải tệp JSON cục bộ trong trình duyệt.
fetch
sẽ báo lỗi nếu bạn cố tải một tệp cục bộ. Ví dụ: giả sử bạn có tệp JSON chứa một số câu chuyện cười:
[
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
},
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "ae-78cogr-cb6x9hluwqtw",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/ae-78cogr-cb6x9hluwqtw",
"value": "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris."
}
]
Và bạn muốn phân tích nó và tạo một danh sách truyện cười trên một trang HTML đơn giản.
Nếu bạn tạo một trang có nội dung sau và mở trang đó trong trình duyệt của mình:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>Fetch Local JSON</title>
</head>
<script>
fetch("./jokes.json", { mode: "no-cors" }) // disable CORS because path does not contain http(s)
.then((res) => res.json())
.then((data) => console.log(data));
</script>
</html>
Bạn sẽ thấy điều này trong bảng điều khiển:
Fetch API cannot load file://<path>/jokes.json. URL scheme "file" is not supported
Theo mặc định, các trình duyệt không cho phép truy cập vào các tệp cục bộ vì lý do bảo mật. Đây là một điều tốt và bạn không nên cố gắng khắc phục hành vi này.
Thay vào đó, điều tốt nhất cần làm là chuyển đổi tệp JSON cục bộ thành JavaScript. May mắn thay, điều này khá dễ dàng vì cú pháp JSON rất giống với JavaScript.
Tất cả những gì bạn cần làm là tạo một tệp mới và khai báo JSON của bạn dưới dạng một biến:
const jokes = [
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
},
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "ae-78cogr-cb6x9hluwqtw",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/ae-78cogr-cb6x9hluwqtw",
"value": "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris."
}
]
Và thêm nó vào trang của bạn dưới dạng một tập lệnh riêng:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<title>Fetch Local JSON</title>
</head>
<script src="https://www.freecodecamp.org/news/json-stringify-example-how-to-parse-a-json-object-with-javascript/jokes.js"></script>
<script>
console.log(jokes);
</script>
</html>
Bạn sẽ có thể sử dụng jokes
mảng tự do trong mã của bạn.
Bạn cũng có thể sử dụng JavaScript modules
để làm điều tương tự, nhưng điều đó hơi nằm ngoài phạm vi của bài viết này.
Nhưng nếu bạn muốn làm việc với các tệp JSON cục bộ và đã cài đặt Node.js thì sao? Bây giờ chúng ta hãy xem làm thế nào để làm điều đó.
Cách phân tích cú pháp JSON trong Node.js
Node.js là thời gian chạy JavaScript cho phép bạn chạy JavaScript bên ngoài trình duyệt. Bạn có thể đọc tất cả về Node.js tại đây.
Cho dù bạn sử dụng Node.js để chạy mã cục bộ trên máy tính của mình hay để chạy toàn bộ ứng dụng web trên máy chủ, bạn nên biết cách làm việc với JSON.
Đối với các ví dụ sau, chúng tôi sẽ sử dụng cùng một jokes.json
tập tin:
[
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "elgv2wkvt8ioag6xywykbq",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/elgv2wkvt8ioag6xywykbq",
"value": "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
},
{
"categories": ["dev"],
"created_at": "2020-01-05 13:42:19.324003",
"icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
"id": "ae-78cogr-cb6x9hluwqtw",
"updated_at": "2020-01-05 13:42:19.324003",
"url": "https://api.chucknorris.io/jokes/ae-78cogr-cb6x9hluwqtw",
"value": "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris."
}
]
Cách phân tích tệp JSON bằng require()
Hãy bắt đầu với phương pháp đơn giản nhất.
Nếu bạn có tệp JSON cục bộ, tất cả những gì bạn cần làm là sử dụng require()
để tải nó giống như bất kỳ mô-đun Node.js nào khác:
const jokes = require('./jokes.json');
Tệp JSON sẽ được phân tích cú pháp tự động cho bạn và bạn có thể bắt đầu sử dụng nó trong dự án của mình:
const jokes = require('./jokes.json');
console.log(jokes[0].value); // "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
Lưu ý rằng đây là đồng bộ, nghĩa là chương trình của bạn sẽ dừng cho đến khi nó phân tích cú pháp toàn bộ tệp trước khi tiếp tục. Các tệp JSON thực sự lớn có thể khiến chương trình của bạn chạy chậm lại, vì vậy hãy cẩn thận với điều đó.
Ngoài ra, vì việc phân tích cú pháp JSON theo cách này sẽ tải toàn bộ nội dung vào bộ nhớ, nên sử dụng phương pháp này cho các tệp JSON tĩnh sẽ tốt hơn. Nếu tệp JSON thay đổi trong khi chương trình của bạn đang chạy, bạn sẽ không có quyền truy cập vào những thay đổi đó cho đến khi bạn khởi động lại chương trình của mình và phân tích cú pháp tệp JSON được cập nhật.
Cách phân tích tệp JSON bằng fs.readFileSync(
) và JSON.parse()
Đây là cách truyền thống hơn (vì thiếu thuật ngữ tốt hơn) để phân tích các tệp JSON trong các dự án Node.js – hãy đọc tệp bằng fs
(hệ thống tệp), sau đó phân tích cú pháp bằng JSON.parse()
.
Hãy xem làm thế nào để làm điều này với fs.readFileSync()
phương pháp. Đầu tiên, thêm fs
mô-đun cho dự án của bạn:
const fs = require('fs');
Sau đó, tạo một biến mới để lưu trữ đầu ra của jokes.json
tập tin và đặt nó bằng fs.readFileSync()
:
const fs = require('fs');
const jokesFile = fs.readFileSync();
fs.readFileSync()
có một vài đối số. Đầu tiên là đường dẫn đến tệp bạn muốn đọc:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json');
Nhưng nếu bạn đăng nhập jokesFile
vào bảng điều khiển bây giờ, bạn sẽ thấy một cái gì đó như thế này:
<Buffer 5b 0a 20 20 7b 0a 20 20 20 20 22 63 61 74 65 67 6f 72 69 65 73 22 3a 20 5b 22 64 65 76 22 5d 2c 0a 20 20 20 20 22 63 72 65 61 74 65 64 5f 61 74 22 3a ... 788 more bytes>
Điều đó chỉ có nghĩa là fs
mô-đun đang đọc tệp, nhưng nó không biết mã hóa hoặc định dạng của tệp. fs
có thể được sử dụng để tải khá nhiều tệp bất kỳ chứ không chỉ những tệp dựa trên văn bản như JSON, vì vậy chúng tôi cần cho nó biết tệp được mã hóa như thế nào.
Đối với các tệp dựa trên văn bản, mã hóa thường là utf8
:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
Bây giờ nếu bạn đăng nhập jokesFile
vào bảng điều khiển, bạn sẽ thấy nội dung của tệp.
Nhưng cho đến nay chúng tôi chỉ đọc tệp và nó vẫn là một chuỗi. Chúng ta sẽ cần sử dụng một phương pháp khác để phân tích cú pháp jokesFile
thành một đối tượng hoặc mảng JavaScript có thể sử dụng được.
Để làm điều đó, chúng tôi sẽ sử dụng JSON.parse()
:
const fs = require('fs');
const jokesFile = fs.readFileSync('./jokes.json', 'utf8');
const jokes = JSON.parse(jokesFile);
console.log(jokes[0].value); // "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
Như tên cho thấy, JSON.parse()
lấy một chuỗi JSON và phân tích nó thành một đối tượng JavaScript bằng chữ hoặc mảng.
Giống như với require
phương pháp trên, fs.readFileSync()
là một phương thức đồng bộ, có nghĩa là nó có thể khiến chương trình của bạn chạy chậm lại nếu nó đang đọc một tệp lớn, JSON hoặc cách khác.
Ngoài ra, nó chỉ đọc tệp một lần và tải nó vào bộ nhớ. Nếu tệp thay đổi, bạn sẽ cần đọc lại tệp vào một lúc nào đó. Để làm mọi việc dễ dàng hơn, bạn có thể muốn tạo một chức năng đơn giản để đọc tệp.
Đây là những gì có thể trông giống như:
const fs = require('fs');
const readFile = path => fs.readFileSync(path, 'utf8');
const jokesFile1 = readFile('./jokes.json');
const jokes1 = JSON.parse(jokesFile1);
console.log(jokes1[0].value); // "Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris."
// the jokes.json file changes at some point
const jokesFile2 = readFile('./jokes.json');
const jokes2 = JSON.parse(jokesFile2);
console.log(jokes2[0].value); // "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
Cách phân tích cú pháp JSON bằng fs.readFile(
) và JSON.parse()
Các fs.readFile()
phương pháp rất giống với fs.readFileSync()
, ngoại trừ việc nó hoạt động không đồng bộ. Điều này thật tuyệt nếu bạn có một tệp lớn để đọc và bạn không muốn nó chứa phần còn lại của mã của bạn.
Đây là một ví dụ cơ bản:
const fs = require('fs');
fs.readFile('./jokes.json', 'utf8');
Cho đến nay điều này có vẻ tương tự như những gì chúng tôi đã làm với fs.readFileSync()
ngoại trừ việc chúng ta không gán nó cho một biến như jokesFile
. Bởi vì nó không đồng bộ, bất kỳ mã nào sau fs.readFile()
nó sẽ chạy trước khi đọc xong tệp.
Thay vào đó, chúng tôi sẽ sử dụng hàm gọi lại và phân tích cú pháp JSON bên trong nó:
const fs = require('fs');
fs.readFile('./jokes.json', 'utf8', (err, data) => {
if (err) console.error(err);
const jokes = JSON.parse(data);
console.log(jokes[0].value);
});
console.log("This will run first!");
Cái nào in phần sau ra bàn điều khiển:
This will run first!
Chuck Norris's keyboard doesn't have a Ctrl key because nothing controls Chuck Norris.
thích với fs.readFileSync()
, fs.readFile()
tải tệp vào bộ nhớ, nghĩa là bạn sẽ cần đọc lại tệp nếu tệp thay đổi.
Ngoài ra, mặc dù fs.readFile()
không đồng bộ, cuối cùng nó sẽ tải toàn bộ tệp mà nó đang đọc vào bộ nhớ. Nếu bạn có một tệp lớn, tốt hơn hết là xem xét các luồng Node.js.
Cách xâu chuỗi JSON với JSON.stringify()
trong Node.js
Cuối cùng, nếu bạn đang phân tích cú pháp JSON bằng Node.js, thì rất có thể bạn sẽ cần trả về JSON vào một thời điểm nào đó, có thể dưới dạng phản hồi API.
May mắn thay, cách này hoạt động giống như trong trình duyệt – chỉ cần sử dụng JSON.stringify()
để chuyển đổi các mảng hoặc ký tự đối tượng JavaScript thành một chuỗi JSON:
const newJoke = {
categories: ['dev'],
value: "Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."
};
console.log(JSON.stringify(newJoke)); // {"categories":["dev"],"value":"Chuck Norris's keyboard is made up entirely of Cmd keys because Chuck Norris is always in command."}
Và thế là xong! Chúng tôi đã trình bày mọi thứ bạn cần biết về cách làm việc với JSON trong trình duyệt và trong các dự án Node.js.
Bây giờ hãy ra khỏi đó và phân tích cú pháp hoặc xâu chuỗi JSON theo nội dung trái tim của bạn.
Tôi đã bỏ lỡ một cái gì đó? Làm cách nào để bạn phân tích cú pháp JSON trong các dự án của mình? Hãy cho tôi biết trên Twitter.