使用Json作为数据库
使用 JSON 文件作为数据库来存储游戏数据是一个简单的实现方式,尤其对于小型项目或原型开发非常有效。虽然 JSON 文件本身不具备数据库的高级功能(如事务、索引、并发访问等),但你仍然可以通过 TypeScript 实现增删改查(CRUD)操作。以下是如何使用 JSON 文件来实现这些功能的具体步骤。
1. 准备工作
首先,确保你已经有一个 JSON 文件来存储数据,假设它存储在 gameData.json
文件中,并且数据格式如下:
{
"nodes": [
{
"id": 1,
"name": "Hero",
"description": "The brave hero of the story.",
"status": "alive"
},
{
"id": 2,
"name": "Villain",
"description": "The evil villain who seeks to conquer the world.",
"status": "alive"
}
]
}
2. 操作 JSON 文件
为了实现增删改查操作,我们需要能够读取和修改 JSON 文件。通常使用 fs
(文件系统模块)来读取和写入文件。我们还需要一个函数来将数据转换为 JSON 格式,以便于保存。
安装必要的依赖
npm install fs-extra
fs-extra
是一个比 fs
更强大的文件操作库,支持异步和同步的 API,还提供了一些额外的便利方法,如 json()
来处理 JSON 文件。
3. 实现增删改查操作
3.1 增加节点(Create)
要向 JSON 文件中添加新节点,你需要先读取当前数据,更新它,然后写回文件。
import * as fs from 'fs-extra';
interface GameNode {
id: number;
name: string;
description: string;
status?: string;
additionalInfo?: any;
}
interface GameData {
nodes: GameNode[];
}
// 读取 JSON 文件
async function readData(): Promise<GameData> {
const data = await fs.readJson('gameData.json');
return data;
}
// 写入 JSON 文件
async function writeData(data: GameData): Promise<void> {
await fs.writeJson('gameData.json', data, { spaces: 2 });
}
// 增加节点
async function addNode(newNode: GameNode) {
const data = await readData();
data.nodes.push(newNode);
await writeData(data);
console.log('Node added successfully!');
}
// 示例:增加一个新的节点
const newNode: GameNode = {
id: 3,
name: "Potion",
description: "A health potion that restores health.",
status: "available",
};
addNode(newNode);
3.2 删除节点(Delete)
删除节点时,我们根据节点的 id
找到它并删除。
// 删除节点
async function deleteNode(nodeId: number) {
const data = await readData();
const index = data.nodes.findIndex(node => node.id === nodeId);
if (index !== -1) {
data.nodes.splice(index, 1);
await writeData(data);
console.log('Node deleted successfully!');
} else {
console.log('Node not found!');
}
}
// 示例:删除 id 为 2 的节点
deleteNode(2);
3.3 更新节点(Update)
更新节点时,我们根据 id
查找并修改节点的属性。
// 更新节点
async function updateNode(updatedNode: GameNode) {
const data = await readData();
const index = data.nodes.findIndex(node => node.id === updatedNode.id);
if (index !== -1) {
data.nodes[index] = updatedNode;
await writeData(data);
console.log('Node updated successfully!');
} else {
console.log('Node not found!');
}
}
// 示例:更新 id 为 1 的节点
const updatedNode: GameNode = {
id: 1,
name: "Updated Hero",
description: "The updated description of the hero.",
status: "injured"
};
updateNode(updatedNode);
3.4 查询节点(Read)
查询节点时,可以根据 id
来获取某个节点,或者根据其他条件筛选。
// 查询节点
async function getNodeById(nodeId: number): Promise<GameNode | undefined> {
const data = await readData();
return data.nodes.find(node => node.id === nodeId);
}
// 示例:查询 id 为 1 的节点
getNodeById(1).then(node => {
if (node) {
console.log('Found node:', node);
} else {
console.log('Node not found!');
}
});
3.5 查询所有节点
你还可以查询所有节点或过滤特定的节点。
// 获取所有节点
async function getAllNodes(): Promise<GameNode[]> {
const data = await readData();
return data.nodes;
}
// 示例:获取所有节点
getAllNodes().then(nodes => {
console.log('All nodes:', nodes);
});
4. 综合代码示例
综合起来,你可以创建一个简单的模块来处理这些操作:
import * as fs from 'fs-extra';
interface GameNode {
id: number;
name: string;
description: string;
status?: string;
additionalInfo?: any;
}
interface GameData {
nodes: GameNode[];
}
// 读取和写入数据
async function readData(): Promise<GameData> {
return fs.readJson('gameData.json');
}
async function writeData(data: GameData): Promise<void> {
await fs.writeJson('gameData.json', data, { spaces: 2 });
}
// 增加、删除、更新和查询节点的函数
async function addNode(newNode: GameNode) {
const data = await readData();
data.nodes.push(newNode);
await writeData(data);
console.log('Node added successfully!');
}
async function deleteNode(nodeId: number) {
const data = await readData();
const index = data.nodes.findIndex(node => node.id === nodeId);
if (index !== -1) {
data.nodes.splice(index, 1);
await writeData(data);
console.log('Node deleted successfully!');
} else {
console.log('Node not found!');
}
}
async function updateNode(updatedNode: GameNode) {
const data = await readData();
const index = data.nodes.findIndex(node => node.id === updatedNode.id);
if (index !== -1) {
data.nodes[index] = updatedNode;
await writeData(data);
console.log('Node updated successfully!');
} else {
console.log('Node not found!');
}
}
async function getNodeById(nodeId: number): Promise<GameNode | undefined> {
const data = await readData();
return data.nodes.find(node => node.id === nodeId);
}
async function getAllNodes(): Promise<GameNode[]> {
const data = await readData();
return data.nodes;
}
总结
通过使用 fs
或 fs-extra
模块,我们可以通过读取、修改、删除和写入 JSON 文件来实现基本的 CRUD 操作。虽然这种方法适用于小型项目,但对于大规模的生产应用,建议使用专业的数据库(如 MySQL、PostgreSQL、MongoDB 等),以便更好地处理并发、索引、查询优化等问题。