使用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;
}

总结

通过使用 fsfs-extra 模块,我们可以通过读取、修改、删除和写入 JSON 文件来实现基本的 CRUD 操作。虽然这种方法适用于小型项目,但对于大规模的生产应用,建议使用专业的数据库(如 MySQL、PostgreSQL、MongoDB 等),以便更好地处理并发、索引、查询优化等问题。

posted @ 2025-01-06 14:17  多见多闻  阅读(351)  评论(0)    收藏  举报