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

Mongoose数据转JSON遇循环结构错误,求ng-table动态生成方案

解决方案:修复循环引用错误+自动适配ng-table动态表头

嘿,我来帮你搞定这两个问题:先是解决那个「循环结构转JSON」的报错,再实现自动提取表头、格式化数据并适配ng-table的需求!


1. 先搞定循环引用的TypeError

你遇到这个错误,是因为从Mongoose拿到的routput不是纯JavaScript对象,而是Mongoose Document实例——这些实例自带了和数据库连接、模型相关的属性(比如base、connections),形成了循环引用,直接用JSON.stringify就会炸。

解决方法有两种,选一种就行:

  • 查询时直接返回纯对象:在Mongoose查询里加.lean(),这样数据库返回的就是普通JS对象,没有额外的Mongoose属性:
    // 示例:查询时用lean()
    YourModel.find({/* 查询条件 */}).lean().exec((err, routpu) => {
      // 这里的routput就是纯JS对象数组,不会有循环引用
    });
    
  • 把已有的Document转成纯对象:如果已经拿到了Document实例,用.toObject()或者.toJSON()转换:
    // 把Mongoose文档数组转成纯JS对象数组
    const plainData = routpu.map(doc => doc.toObject());
    

2. 自动提取表头+格式化特殊字段(_id/日期)

接下来写一个通用函数,不管传入什么数据,都能自动提取表头,同时把_id转成字符串、日期转成YYYY-MM-DD格式:

function formatReportOutput(data) {
  // 处理空数据的情况
  if (!Array.isArray(data) || data.length === 0) {
    return { headers: [], values: [] };
  }

  // 自动提取表头:取第一个数据对象的所有键
  const headers = Object.keys(data[0]);

  // 格式化每一行数据,处理_id和日期
  const values = data.map(item => {
    return headers.map(key => {
      const value = item[key];
      // 处理MongoDB的ObjectId
      if (key === '_id' && value?.toString) {
        return value.toString();
      }
      // 处理ISODate,转成YYYY-MM-DD
      if (value instanceof Date) {
        return value.toISOString().split('T')[0];
      }
      // 其他类型直接返回
      return value;
    });
  });

  return { headers, values };
}

调用示例:

// 假设plainData是已经转成纯JS对象的数据
const formattedResult = formatReportOutput(plainData);
// formattedResult.headers = ["_id", "INumber", "IID", "DateReceived"]
// formattedResult.values = [["59920689253dfa0544f26b93", "535264", "25544825", "2017-08-14"]]

3. 适配ng-table实现自动渲染

现在把格式化后的数据传给AngularJS,动态生成ng-table的列和数据:

控制器代码

app.controller('ReportController', function($scope, $http, ngTableParams) {
  // 从后端接口获取格式化后的数据(或者直接在前端处理)
  $http.get('/routes/data')
    .then(function(response) {
      const { headers, values } = response.data;

      // 把二维数组转成ng-table需要的对象数组:每个元素是{表头: 值}的结构
      $scope.tableData = values.map(row => {
        const rowObj = {};
        headers.forEach((key, index) => {
          rowObj[key] = row[index];
        });
        return rowObj;
      });

      // 自动生成ng-table的列配置
      $scope.tableColumns = headers.map(key => ({
        title: key, // 表头显示的文字
        field: key  // 对应数据对象的属性名
      }));

      // 初始化ng-table参数
      $scope.tableParams = new ngTableParams({
        page: 1,    // 默认页码
        count: 10   // 默认每页条数
      }, {
        dataset: $scope.tableData
      });
    });
});

模板代码

<div ng-controller="ReportController">
  <table ng-table="tableParams" class="table table-striped">
    <tr ng-repeat="row in $data">
      <td ng-repeat="col in tableColumns" 
          data-title="col.title" 
          sortable="col.field">
        {{ row[col.field] }}
      </td>
    </tr>
  </table>
</div>

这样不管你传入什么结构的数据库数据,都能自动提取表头、格式化特殊字段,然后在ng-table里自动渲染,完全不需要硬编码表头!


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:43:52