JSON (JavaScript Object Notation) là cách viết dữ liệu dưới dạng chuỗi chữ, nhìn gần giống object của JS. Vì là chuỗi nên nó lưu vào file, gửi qua mạng hay cất vào bộ nhớ trình duyệt được. Mini game dùng JSON để lưu điểm cao, lưu tiến trình, đọc file cấu hình level.
JSON trông ra sao
const json = '{"name":"Aki","hp":100,"items":["kiếm","bình máu"]}';
Giống object, nhưng luật chặt hơn:
- Tên key phải nằm trong nháy kép:
"name", không đượcnamehay'name'. - Chuỗi dùng nháy kép.
- Không có dấu phẩy thừa ở cuối.
- Không chứa hàm,
undefinedhay comment.
JSON.stringify: object thành chuỗi
const save = {
playerName: "Aki",
level: 4,
inventory: ["kiếm", "khiên"],
};
const text = JSON.stringify(save);
console.log(text);
// {"playerName":"Aki","level":4,"inventory":["kiếm","khiên"]}
console.log(typeof text); // string
Muốn dễ đọc khi debug, truyền thêm số dấu cách thụt đầu dòng:
console.log(JSON.stringify(save, null, 2));
// {
// "playerName": "Aki",
// "level": 4,
// "inventory": [
// "kiếm",
// "khiên"
// ]
// }
JSON.parse: chuỗi thành object
const text = '{"playerName":"Aki","level":4}';
const data = JSON.parse(text);
console.log(data.level); // 4
console.log(data.level + 1); // 5
Kết quả là object thật, dùng dấu chấm đọc được, số vẫn là số.
Lỗi hay gặp:
JSON.parsemột chuỗi viết sai luật JSON, ví dụ key không có nháy:JSON.parse("{level: 4}"). JS báoSyntaxError: Expected property name or '}' in JSON at position 1. Chuỗi rỗng hayundefinedcũng lỗi. Dữ liệu từ ngoài vào thì bọcJSON.parsetrongtry...catch.
Lưu điểm cao với localStorage
localStorage là chỗ lưu dữ liệu của trình duyệt, còn nguyên sau khi tắt tab hay tắt máy. Nó chỉ lưu chuỗi, theo cặp key và giá trị.
localStorage.setItem("highScore", "250");
console.log(localStorage.getItem("highScore")); // 250
console.log(localStorage.getItem("unknownKey")); // null
Chỗ người mới hay vấp: đưa object thẳng vào setItem.
const record = { name: "Aki", score: 250 };
localStorage.setItem("record", record);
console.log(localStorage.getItem("record")); // [object Object]
localStorage tự đổi object thành chuỗi bằng cách thô nhất, ra "[object Object]", dữ liệu mất sạch. Cách đúng: JSON.stringify trước khi lưu, JSON.parse sau khi đọc.
const record = { name: "Aki", score: 250 };
localStorage.setItem("record", JSON.stringify(record));
const loaded = JSON.parse(localStorage.getItem("record"));
console.log(loaded.score); // 250
Ví dụ: bảng điểm cao
Ghép lại thành hai hàm cho mini game. Lần đầu chơi chưa có dữ liệu, getItem trả về null, nên dùng ?? để có mảng rỗng mặc định.
const STORAGE_KEY = "highScores";
function loadHighScores() {
try {
return JSON.parse(localStorage.getItem(STORAGE_KEY)) ?? [];
} catch {
return [];
}
}
function saveScore(name, score) {
const scores = loadHighScores();
scores.push({ name, score });
scores.sort((a, b) => b.score - a.score);
const top5 = scores.slice(0, 5);
localStorage.setItem(STORAGE_KEY, JSON.stringify(top5));
return top5;
}
saveScore("Aki", 250);
saveScore("Mira", 410);
console.log(loadHighScores());
// [ { name: 'Mira', score: 410 }, { name: 'Aki', score: 250 } ]
Vài điểm trong code:
JSON.parse(null)ranull, nên?? []biến nó thành mảng rỗng.try...catchphòng trường hợp dữ liệu cũ bị hỏng. Không có nó, một chuỗi lỗi là game không mở được. Cáchtry...catchhoạt động có ở trang Async await.{ name, score }là cách viết tắt của{ name: name, score: score }.sort((a, b) => b.score - a.score)xếp điểm từ cao xuống thấp.
localStorage chỉ có trên trình duyệt. Mỗi trang web có vùng lưu riêng, và người chơi xoá dữ liệu duyệt web là mất. Đừng lưu mật khẩu hay thông tin nhạy cảm vào đó.
Bài tập
Viết hai hàm saveProgress(level, gold) lưu object { level, gold } vào key "progress", và loadProgress() đọc lại. Nếu chưa có dữ liệu thì trả về { level: 1, gold: 0 }.
Xem đáp án
function saveProgress(level, gold) {
localStorage.setItem("progress", JSON.stringify({ level, gold }));
}
function loadProgress() {
const text = localStorage.getItem("progress");
if (text === null) {
return { level: 1, gold: 0 };
}
return JSON.parse(text);
}
saveProgress(3, 120);
console.log(loadProgress()); // { level: 3, gold: 120 }