使用 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 等),以便更好地处理并发、索引、查询优化等问题。