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

如何将fs.readFile读取的JS对象字面量字符串转换为JS对象?

解决JS非标准对象字符串转JS对象的问题

你拿到的字符串是包含函数调用的JS对象字面量,不是严格的JSON格式,所以JSON.parse没法处理。下面给两种Node.js环境下可行的解决办法:

方法一:用Node.js内置的vm模块(推荐)

vm模块能在隔离的上下文里执行JS代码,刚好适配这种带自定义函数的对象语法。先模拟env相关函数的行为,再执行字符串拿到对象:

const vm = require('vm');

// 假设你已经通过fs.readFile拿到了content字符串
const content = "{ host: env(\"HOST\", \"0.0.0.0\"), port: env.int(\"PORT\", 1337), app: { keys: env.array(\"APP_KEYS\"), },}";

// 模拟env系列函数,根据你的实际需求调整逻辑
const context = vm.createContext({
  env: {
    (key, defaultValue) => process.env[key] || defaultValue,
    int: (key, defaultValue) => {
      const val = process.env[key];
      return val ? parseInt(val, 10) : defaultValue;
    },
    array: (key) => {
      const val = process.env[key];
      return val ? val.split(',') : [];
    }
  }
});

// 把目标字符串包装成函数返回值,降低执行风险
const script = new vm.Script(`(() => { return ${content}; })()`);
// 执行脚本拿到可操作的JS对象
const configObj = script.runInContext(context);

console.log(configObj); // 现在就能对这个对象做检查、修改了

注意:如果你的env函数有其他逻辑,要同步调整context里的模拟函数;另外确保要执行的字符串是可信的,避免恶意代码注入。

方法二:AST解析(适合高安全要求场景)

如果不想执行代码,也可以用@babel/parser把字符串解析成抽象语法树(AST),再遍历AST提取数据:

const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;

const content = "{ host: env(\"HOST\", \"0.0.0.0\"), port: env.int(\"PORT\", 1337), app: { keys: env.array(\"APP_KEYS\"), },}";

// 把字符串解析成AST
const ast = parser.parseExpression(content);

const configObj = {};

// 遍历AST提取配置值
traverse(ast, {
  ObjectProperty(path) {
    const key = path.node.key.name;
    const valueNode = path.node.value;

    // 处理env函数调用
    if (valueNode.type === 'CallExpression') {
      const callee = valueNode.callee;
      const args = valueNode.arguments;

      if (callee.type === 'Identifier' && callee.name === 'env') {
        const envKey = args[0].value;
        const defaultValue = args[1].value;
        configObj[key] = process.env[envKey] || defaultValue;
      } else if (callee.type === 'MemberExpression' && callee.object.name === 'env') {
        const method = callee.property.name;
        const envKey = args[0].value;
        const defaultValue = args[1]?.value;

        if (method === 'int') {
          configObj[key] = process.env[envKey] ? parseInt(process.env[envKey], 10) : defaultValue;
        } else if (method === 'array') {
          configObj[key] = process.env[envKey] ? process.env[envKey].split(',') : [];
        }
      }
    } else if (valueNode.type === 'ObjectExpression') {
      // 处理嵌套对象(比如示例里的app)
      configObj[key] = {};
      path.traverse({
        ObjectProperty(nestedPath) {
          const nestedKey = nestedPath.node.key.name;
          const nestedValueNode = nestedPath.node.value;
          // 处理嵌套里的env.array调用
          if (nestedValueNode.type === 'CallExpression') {
            const callee = nestedValueNode.callee;
            const args = nestedValueNode.arguments;
            if (callee.type === 'MemberExpression' && callee.object.name === 'env' && callee.property.name === 'array') {
              const envKey = args[0].value;
              configObj[key][nestedKey] = process.env[envKey] ? process.env[envKey].split(',') : [];
            }
          }
        }
      });
    }
  }
});

console.log(configObj);

这种方法不需要执行代码,安全性更高,但需要自己处理AST的遍历逻辑,适合对安全要求严格的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:05:32