在现代软件开发中,数据是核心,当我们谈论数据存储时,脑海中浮现的往往是MySQL、PostgreSQL或MongoDB等传统数据库系统,对于许多小型项目、原型开发或特定应用场景,一个看似“原始”的方案却异常高效和流行——那就是直接使用JSON文件作为数据库,本文将深入探讨如何“拿”到并使用这种轻量级的JSON数据库,包括其核心概念、实现方式、适用场景以及固有的优缺点。

核心概念:JSON作为数据库
将JSON文件用作数据库,本质上是一种基于文件的存储方案,所有的数据都持久化在一个或多个.json文件中,这种“数据库”的结构通常是一个对象或一个数组,数组中的每个元素代表一条记录。
一个简单的用户数据库users.json可能如下所示:
{
"users": [
{
"id": 1,
"name": "张三",
"email": "zhangsan@example.com"
},
{
"id": 2,
"name": "李四",
"email": "lisi@example.com"
}
]
}
对这种“数据库”的操作,遵循着经典的CRUD(创建、读取、更新、删除)模型,但其实现方式与传统数据库截然不同:
- 创建:读取JSON文件,在内存中解析为JavaScript对象或Python字典,向数组中追加一个新对象,然后将整个结构重新序列化为JSON字符串,最后覆盖写入原文件。
- 读取:读取整个JSON文件,解析后在内存中进行查询和筛选。
- 更新:读取、解析、在内存中找到并修改目标对象,再将整个结构重新写入文件。
- 删除:读取、解析、从内存中移除目标对象,再将整个结构重新写入文件。
如何“拿”——三种主流实现方式
“拿”JSON数据库,指的是如何与这些JSON文件进行交互,根据项目复杂度的不同,主要有以下三种方式。
原生文件读写
这是最基础、最直接的方式,无需任何外部依赖,几乎所有的编程语言都提供了读取和写入文件的内置功能。
以Node.js为例,一个添加用户的操作可能如下:
const fs = require('fs');
// 1. 读取文件
let data = JSON.parse(fs.readFileSync('users.json', 'utf-8'));
// 2. 在内存中修改数据
const newUser = { id: 3, name: "王五", email: "wangwu@example.com" };
data.users.push(newUser);
// 3. 将整个数据写回文件
fs.writeFileSync('users.json', JSON.stringify(data, null, 2));
这种方式简单直观,但缺点非常明显:每次写入都需要重写整个文件,对于数据量大的文件性能低下;且无法处理并发请求,如果两个操作同时读写,极易导致数据损坏或丢失。

使用轻量级库
为了解决原生操作的痛点,社区诞生了许多轻量级的库,它们封装了繁琐的读写逻辑,并提供了更友好的API,在Node.js生态中,lowdb和json-server是其中的杰出代表。
lowdb是一个小巧的本地JSON数据库,它提供了类似Lodash的链式查询API,让数据操作变得非常优雅。
使用lowdb,上面的添加操作可以简化为:
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('users.json');
const db = low(adapter);
// 直接操作,库会自动处理读写
db.get('users').push({ id: 3, name: "王五", email: "wangwu@example.com" }).write();
这类库极大地提升了开发效率,并部分缓解了并发问题(通常通过简单的文件锁实现)。
构建伪RESTful API
对于前端开发者或需要模拟后端API的场景,json-server是一个神器,它能让你在不到一分钟的时间内,将一个JSON文件变成一个功能完备的RESTful API服务。
你只需要创建一个db.json文件,然后运行命令:npx json-server --watch db.json。json-server就会自动为你生成如下API端点:
GET /users- 获取所有用户GET /users/1- 获取ID为1的用户POST /users- 创建一个新用户PUT /users/1- 更新ID为1的用户DELETE /users/1- 删除ID为1的用户
这种方式使得“拿”数据的过程完全符合现代Web开发的模式,非常适合前后端分离项目的初期开发和测试。

下表小编总结了这三种方式的特点:
| 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 原生文件读写 | 无任何依赖,控制力强 | 性能差,并发风险高,代码冗余 | 极简单的脚本,一次性数据迁移 |
| 使用轻量级库 | API友好,简化操作,开发效率高 | 扩展性有限,非真正的数据库解决方案 | 快速原型开发,小型个人项目,静态网站数据源 |
| 构建伪API | 快速模拟后端,支持RESTful交互 | 同样不适合生产高并发环境 | 前端开发、测试、演示、教学 |
优势与局限
优势:
- 零配置:无需安装、配置或管理数据库服务器。
- 高度可移植:数据就是单个文件,复制、备份、迁移极其方便。
- 人类可读:JSON格式清晰,便于直接查看和手动编辑。
- 开发友好:非常适合快速启动项目和进行概念验证。
局限:
- 并发问题:这是其最致命的弱点,无法安全地处理多个进程或线程的同时写入。
- 性能瓶颈:数据量大时,读写整个文件会变得非常缓慢。
- 缺乏高级功能:没有索引、事务、认证、权限管理等现代数据库的核心特性。
- 数据一致性风险:应用崩溃或写入中断可能导致整个文件损坏。
“拿”JSON数据库,意味着选择了一种轻量、灵活但功能受限的数据管理方案,它并非要取代传统数据库,而是在其适用的领域内发挥巨大价值,对于个人项目、小型工具、快速原型、前端数据模拟或是配置文件管理,JSON文件是一个无与伦比的优秀选择,一旦项目规模扩大,涉及多用户并发或需要复杂查询与事务支持,就必须迁移到真正的数据库系统中,理解其边界,是用好这把“轻剑”的关键。
相关问答FAQs
问1:JSON数据库适合什么规模的项目? 答: JSON数据库(即基于JSON文件的存储)最适合小规模、低流量、对并发要求不高的项目,具体包括:个人博客、作品集网站、小型静态站点的数据源、移动应用的本地配置存储、前端开发的原型验证以及教学和演示项目,对于任何需要处理高并发读写、数据量较大或要求事务完整性的生产级应用(如电商网站、社交平台、金融系统),则完全不适合,应选择MySQL、PostgreSQL或MongoDB等专业数据库。
问2:如何处理JSON文件的并发读写问题? 答: 原生的JSON文件读写无法直接解决并发问题,因为“读取-修改-写入”这个操作不是原子性的,容易导致竞态条件,有几种缓解策略:
- 使用文件锁:在写入文件前,操作系统层面获取一个排他锁(如Node.js中的
proper-lockfile库),确保同一时间只有一个进程能写入,这能显著降低风险,但不能完全消除性能问题。 - 借助轻量级库:像
lowdb这样的库在内部实现了一些基础的同步机制,比手动处理要安全。 - 最终方案:最根本、最可靠的解决方法是放弃JSON文件作为数据库,迁移到为并发设计的真正数据库,专业数据库通过锁机制、事务日志和MVCC(多版本并发控制)等成熟技术来保证并发环境下的数据安全与一致性。