如何在Node.js中不借助外部库验证JSON对象
嘿,我来帮你搞定这个问题!在Node.js环境里不用任何外部库来验证JSON对象,完全可以靠原生JS和Node的基础API实现,下面我分几个常见场景给你拆解具体做法。
1. 基础JSON格式合法性验证
首先,如果你要验证的是JSON字符串(比如从请求体、文件里读出来的内容),第一步得确认它的格式是合法的——毕竟格式不合法的话,连解析成JS对象都做不到。
这里最直接的方法就是用JSON.parse配合try-catch:如果解析过程抛出SyntaxError,就说明格式有问题。
function isValidJsonString(jsonString) { try { // 尝试解析字符串,成功则说明格式合法 JSON.parse(jsonString); return true; } catch (error) { // 捕获语法错误,输出具体问题(可选) if (error instanceof SyntaxError) { console.log(`JSON格式错误:${error.message}`); } return false; } } // 测试用例 const validJson = '{"name": "Alice", "age": 30}'; const invalidJson = '{"name": "Alice", age: 30}'; // age没加引号,属于非法格式 console.log(isValidJsonString(validJson)); // 输出 true console.log(isValidJsonString(invalidJson)); // 输出 false,同时打印错误信息
2. JSON对象的结构与字段验证
很多时候,我们不仅需要格式合法,还得确保解析后的对象符合业务要求——比如必须包含某些字段、字段类型正确、值在合理范围内等等。这时候就得自己写针对性的验证逻辑了。
举个例子:假设我们要验证一个用户对象,要求:
- 必须有
name(非空字符串) - 必须有
age(≥18的整数) - 可选字段
email(如果存在,必须是包含@的字符串)
对应的验证函数可以这么写:
function validateUser(userObj) { // 先检查输入是不是非空对象 if (typeof userObj !== 'object' || userObj === null) { return { valid: false, error: '输入必须是一个非空对象' }; } // 验证必填字段name if (!('name' in userObj)) { return { valid: false, error: '缺少必填字段:name' }; } if (typeof userObj.name !== 'string' || userObj.name.trim().length === 0) { return { valid: false, error: 'name必须是非空字符串' }; } // 验证必填字段age if (!('age' in userObj)) { return { valid: false, error: '缺少必填字段:age' }; } if (typeof userObj.age !== 'number' || !Number.isInteger(userObj.age) || userObj.age < 18) { return { valid: false, error: 'age必须是大于等于18的整数' }; } // 验证可选字段email(仅当存在时检查) if ('email' in userObj) { if (typeof userObj.email !== 'string' || !userObj.email.includes('@')) { return { valid: false, error: 'email必须是包含@的字符串' }; } } // 所有验证通过 return { valid: true, error: null }; } // 测试用例 const validUser = { name: 'Bob', age: 25, email: 'bob@example.com' }; const invalidUser1 = { age: 20 }; // 缺少name字段 const invalidUser2 = { name: '', age: 17 }; // name为空,age小于18 const invalidUser3 = { name: 'Charlie', age: '30' }; // age是字符串类型 console.log(validateUser(validUser)); // { valid: true, error: null } console.log(validateUser(invalidUser1)); // { valid: false, error: '缺少必填字段:name' } console.log(validateUser(invalidUser2)); // { valid: false, error: 'name必须是非空字符串' }
3. 进阶:嵌套对象的递归验证
如果你的JSON对象有嵌套结构(比如用户对象里包含一个地址对象),可以把嵌套部分的验证逻辑抽成单独的函数,然后在主验证函数里递归调用。
比如我们给用户对象加一个可选的address字段,要求它包含street(非空字符串)和city(非空字符串):
// 单独的地址验证函数 function validateAddress(address) { if (typeof address !== 'object' || address === null) { return { valid: false, error: 'address必须是非空对象' }; } if (!('street' in address) || typeof address.street !== 'string' || address.street.trim().length === 0) { return { valid: false, error: 'address.street必须是非空字符串' }; } if (!('city' in address) || typeof address.city !== 'string' || address.city.trim().length === 0) { return { valid: false, error: 'address.city必须是非空字符串' }; } return { valid: true, error: null }; } // 升级用户验证函数,加入地址验证 function validateUserWithAddress(userObj) { // 先做基础的用户验证 const baseResult = validateUser(userObj); if (!baseResult.valid) { return baseResult; } // 如果存在address字段,验证它 if ('address' in userObj) { const addressResult = validateAddress(userObj.address); if (!addressResult.valid) { return addressResult; } } return { valid: true, error: null }; } // 测试 const userWithValidAddr = { name: 'Alice', age: 30, address: { street: '123 Main St', city: 'New York' } }; const userWithInvalidAddr = { name: 'Alice', age: 30, address: { street: '', city: 123 } }; console.log(validateUserWithAddress(userWithValidAddr)); // 验证通过 console.log(validateUserWithAddress(userWithInvalidAddr)); // { valid: false, error: 'address.street必须是非空字符串' }
4. 通用化:基于Schema的验证
如果需要验证多种不同结构的对象,写一堆单独的验证函数会很繁琐。这时候可以把验证规则抽象成Schema配置对象,然后写一个通用的验证器来遍历Schema检查。
比如定义一个用户Schema,然后用通用函数验证:
// 定义用户验证规则的Schema const userSchema = { name: { type: 'string', required: true, validator: (val) => val.trim().length > 0 // 自定义验证逻辑 }, age: { type: 'number', required: true, validator: (val) => Number.isInteger(val) && val >= 18 }, email: { type: 'string', required: false, validator: (val) => val.includes('@') }, address: { type: 'object', required: false, schema: { // 嵌套对象的Schema street: { type: 'string', required: true, validator: (val) => val.trim().length > 0 }, city: { type: 'string', required: true, validator: (val) => val.trim().length > 0 } } } }; // 通用Schema验证函数 function validateWithSchema(obj, schema) { if (typeof obj !== 'object' || obj === null) { return { valid: false, error: '输入必须是非空对象' }; } for (const [field, rules] of Object.entries(schema)) { // 检查必填字段是否存在 if (rules.required && !(field in obj)) { return { valid: false, error: `缺少必填字段:${field}` }; } // 如果字段存在,先检查类型 if (field in obj) { const value = obj[field]; const expectedType = rules.type; // 处理特殊情况:typeof null是object,所以单独判断 if (expectedType !== 'null' && typeof value !== expectedType) { return { valid: false, error: `${field}的类型必须是${expectedType}` }; } // 如果是嵌套对象,递归验证 if (expectedType === 'object' && rules.schema) { const nestedResult = validateWithSchema(value, rules.schema); if (!nestedResult.valid) { return nestedResult; } } // 执行自定义验证函数 if (rules.validator && !rules.validator(value)) { return { valid: false, error: `${field}不符合验证规则` }; } } } return { valid: true, error: null }; } // 测试 const testUser = { name: 'Dave', age: 22, email: 'dave@test.com', address: { street: '456 Oak Ave', city: 'Boston' } }; console.log(validateWithSchema(testUser, userSchema)); // 验证通过 const badUser = { name: '', age: 17, address: { street: '789 Pine Rd' } }; console.log(validateWithSchema(badUser, userSchema)); // { valid: false, error: 'name不符合验证规则' }
内容的提问来源于stack exchange,提问作者user9052801
相关产品推荐
相关产品推荐

