You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为本地JSON文件创建类Mongoose的Schema?(Node.js+EJS)

问题解答

是否需要为JSON文件创建类似MongoDB的Schema?

需要。JSON文件本身是无结构约束的纯文本格式,直接写入数据很容易出现格式不一致、字段缺失、数据类型错误等问题。创建类似Mongoose的Schema可以:

  • 保证数据格式统一,和你熟悉的MongoDB数据规范对齐
  • 自动处理字段校验(比如必填项、格式验证)
  • 统一处理字段转换(比如自动trim字符串)
  • 避免无效数据写入JSON文件

如何创建适配JSON文件的Schema?

你可以自己实现一套Schema验证逻辑,也可以用轻量的第三方库简化开发,下面结合你的Mongoose Schema示例,给出自定义实现的方案,完全贴合你的开发习惯:

1. 定义Schema验证规则

创建loginSchema.js文件,抽离字段规则和校验逻辑:

// loginSchema.js
export const loginSchema = {
  email: {
    type: 'string',
    required: true,
    trim: true,
    validate: (value) => {
      if (!value.match(/^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/)) {
        throw new Error('Email is not valid.');
      }
    }
  },
  password: {
    type: 'string',
    required: true,
    trim: true
  },
  userCity: {
    type: 'string',
    trim: true
  },
  userRegion: {
    type: 'string',
    trim: true
  },
  userCountry: {
    type: 'string',
    trim: true
  },
  userPostal: {
    type: 'string',
    trim: true
  },
  userTimeZone: {
    type: 'string'
  },
  userAgent: {
    type: 'string'
  }
};

2. 实现数据校验与处理工具

创建schemaValidator.js文件,实现类似Mongoose的校验逻辑:

// schemaValidator.js
export function validateAndProcessData(schema, data) {
  const processedData = {};

  // 遍历Schema字段,逐一校验处理
  for (const [field, rules] of Object.entries(schema)) {
    const value = data[field];

    // 必填项校验
    if (rules.required && (value === undefined || value === null)) {
      throw new Error(`Field "${field}" is required`);
    }

    // 非必填字段不存在则跳过
    if (value === undefined && !rules.required) {
      continue;
    }

    // 数据类型校验
    if (typeof value !== rules.type) {
      throw new Error(`Field "${field}" must be of type ${rules.type}`);
    }

    // 处理字符串trim
    if (rules.trim && typeof value === 'string') {
      processedData[field] = value.trim();
    } else {
      processedData[field] = value;
    }

    // 自定义校验逻辑执行
    if (rules.validate) {
      rules.validate(processedData[field]);
    }
  }

  // 可选:禁止Schema外的额外字段(按需开启)
  const extraFields = Object.keys(data).filter(key => !schema.hasOwnProperty(key));
  if (extraFields.length > 0) {
    throw new Error(`Unexpected fields: ${extraFields.join(', ')}`);
  }

  return processedData;
}

3. 在业务代码中使用

在Node.js后端处理表单提交的逻辑里,先校验数据,再写入JSON文件:

// 示例:表单提交处理路由
import { loginSchema } from './loginSchema.js';
import { validateAndProcessData } from './schemaValidator.js';
import fs from 'fs/promises';
import path from 'path';

// JSON文件存储路径
const DATA_FILE = path.join(process.cwd(), 'data', 'logins.json');

export async function handleLoginSubmit(req, res) {
  try {
    // 1. 校验并处理表单数据
    const validatedData = validateAndProcessData(loginSchema, req.body);

    // 2. 读取现有JSON数据
    let existingData = [];
    try {
      const fileContent = await fs.readFile(DATA_FILE, 'utf8');
      existingData = JSON.parse(fileContent);
    } catch (err) {
      // 文件不存在则初始化空数组
      if (err.code === 'ENOENT') {
        existingData = [];
      } else {
        throw err;
      }
    }

    // 3. 添加新数据并写入文件
    existingData.push(validatedData);
    await fs.writeFile(DATA_FILE, JSON.stringify(existingData, null, 2));

    // 4. 返回成功响应
    res.redirect('/success');
  } catch (err) {
    // 处理校验或文件操作错误
    res.status(400).render('error', { message: err.message });
  }
}

可选:用第三方库简化实现

如果不想自己写校验逻辑,可以用yup(语法和Mongoose高度相似):

import * as yup from 'yup';

const loginSchema = yup.object().shape({
  email: yup.string()
    .required('Email is required')
    .matches(/^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/, 'Email is not valid')
    .trim(),
  password: yup.string()
    .required('Password is required')
    .trim(),
  userCity: yup.string().trim(),
  userRegion: yup.string().trim(),
  userCountry: yup.string().trim(),
  userPostal: yup.string().trim(),
  userTimeZone: yup.string(),
  userAgent: yup.string()
});

// 使用方式
const validatedData = await loginSchema.validate(req.body, { abortEarly: false });

内容的提问来源于stack exchange,提问作者Change

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:45:31