Javascript 嵌套数组到平面表的叉积

Javascript 嵌套数组到平面表的叉积,javascript,jquery,html,datatables,Javascript,Jquery,Html,Datatables,我有嵌套对象,对象的深度可以是N,每个对象可以有X个属性以及嵌套到其中的X个对象 问题 1) 在整个循环完成之前,我很难猜测哪些列标题将添加到表中。正如您在我的第一行中所看到的,我只有一列“Name”,但在第二行中,我有嵌套的对象,这些对象向表中添加了更多的列标题 2) 我想让它与jQuery datatable一起工作,而jQuery datatable不适用于上述场景,因为所有行的列数都不相同 3) 我不想硬编码任何东西,因为JSON数据可以是任何东西 这是小提琴: 请注意,JSON是动态的

我有嵌套对象,对象的深度可以是N,每个对象可以有X个属性以及嵌套到其中的X个对象

问题

1) 在整个循环完成之前,我很难猜测哪些列标题将添加到表中。正如您在我的第一行中所看到的,我只有一列“Name”,但在第二行中,我有嵌套的对象,这些对象向表中添加了更多的列标题

2) 我想让它与jQuery datatable一起工作,而jQuery datatable不适用于上述场景,因为所有行的列数都不相同

3) 我不想硬编码任何东西,因为JSON数据可以是任何东西

这是小提琴:

请注意,JSON是动态的,语法将保持不变,但对象和属性的数量+子对象的数量可能会有所不同,因此没有硬编码。。。谢谢

代码

var resultFromWebService = {
  //"odata.metadata": "http://localhost:21088/WcfDataService1.svc/$metadata#Categories&$select=Name,Products,Products/Currency/Symbol",
  "value": [{
    "Products": [],
    "Name": "Meat"
  }, {
    "Products": [{
      "Currency": {
        "ID": 47,
        "Num": 826,
        "Code": "GBP",
        "Description": "United Kingdom Pound",
        "DigitsAfterDecimal": 2,
        "Symbol": "\u00a3",
        "Hide": null,
        "Priority": 1
      },
      "ID": 2425,
      "Name": "303783",
      "ExpiryDate": "2014-02-22T00:00:00",
      "CurrencyID": 47,
      "Sales": "0.00000000000000000000",
      "PreTaxProfitOnProduct": null,
      "Assets": "0.30000000000000000000",
      "BarCode": null,
      "Worth": "0.20000000000000000000",
      "MarketValue": null
    }],
    "Name": "Produce & Vegetable"
  }]
};


var createBody = true;
var $table = $('<table id="myTable" class="defaultResultsFormatting"/>');
var $thead = $('<thead />');
var $tbody = $('<tbody />');
var $headRow = $('<tr/>');
var $parentCells = null;
var columnHeaders = [];
$table.append($thead);
var $resultContainer = createResultsTable(resultFromWebService);
$("#resultTableContainer").append($resultContainer);

//$('#myTable').dataTable();

function createResultsTable(data, title) {
  if (data) { // && data.length > 0) {
    if (createBody) {
      $thead.append($headRow);
      $table.append($tbody);
      createBody = false;
    }
    if (data.length > 0) {
      addColumnHeaders(data[0]);
      $.each(data, function(index, e) {
        populateTable(e);
      });
    } else {
      addColumnHeaders(data);
      populateTable(data);
    }
  } else {
    this.noResults();
  }

  function addColumnHeaders(result) {
    for (var property in result) {
      var type = typeof result[property];
      if (type === 'string' || type === 'number' || type === 'boolean' || result[property] instanceof Date || !result[property]) {
        var mainEntityName = result.__metadata ? result.__metadata.type.split(".").splice(-1)[0] + "." : "";
        mainEntityName = (title ? title + "." : mainEntityName);
        var cName = mainEntityName + property;
        if ($.inArray(cName, columnHeaders) < 0) {
          $headRow.append($('<th />', {
            text: cName
          }));
          columnHeaders.push(cName);
          console.log("columnHeader:" + cName);
        }
      }
    }
  }

  function populateTable(data) {
    var $bodyRow = null;
    if ($parentCells) {
      $bodyRow = $parentCells.clone();
    } else {
      $bodyRow = $('<tr/>');
    }

    var expandedChildResults = [];
    $.each(data, function(index, property) {
      var type = typeof property;
      if (type === 'string' || type === 'number' || type === 'boolean') {
        $bodyRow.append($('<td />', {
          text: property
        }));
      } else if (property instanceof Date) { // DataJS returns the dates as objects and not as strings.
        $bodyRow.append($('<td />', {
          text: property.toDateString()
        }));
      } else if (!property) {
        $bodyRow.append('<td />');
      } else if (typeof property === 'object' && property.results && index !== '__metadata') {
        expandedChildResults.push({
          key: property.results,
          value: index
        });
      } else if (typeof property === 'object' && index !== '__metadata' && index !== '__deferred' && !isPropertyAnObjectWithJustSingle__deferred(property)) {
        expandedChildResults.push({
          key: property,
          value: index
        });
      }
    });

    if (expandedChildResults.length > 0) {
      $.each(expandedChildResults, function(index, childObject) {
        $parentCells = $bodyRow;
        createResultsTable(childObject.key, childObject.value);
      });
      $parentCells = null;
    } else
      $tbody.append($bodyRow);
      console.log($bodyRow);
  }

  function isPropertyAnObjectWithJustSingle__deferred(property) {
    var keys;
    return typeof property === 'object' && // test if it's and object
      (keys = Object.keys(property)).length === 1 && // test if it has just sibgle property
      keys[0] === '__deferred'; // test if that property is '__deferred'
  }

  return $table;
};
var resultFromWebService={
//“odata.metadata”:”http://localhost:21088/WcfDataService1.svc/$metadata#类别&$select=名称、产品、产品/货币/符号“,
“价值”:[{
“产品”:[],
“名称”:“肉”
}, {
“产品”:[{
“货币”:{
“ID”:47,
“Num”:826,
“代码”:“英镑”,
“说明”:“英国镑”,
“数字后十进制”:2,
“符号”:“\u00a3”,
“隐藏”:空,
“优先权”:1
},
“ID”:2425,
“名称”:“303783”,
“到期日”:“2014-02-22T00:00:00”,
“CurrencyID”:47,
“销售”:“0.00000000000000”,
“PreTaxProfitOnProduct”:空,
“资产”:“300000000000000000000”,
“条形码”:空,
“价值”:“0.200000000000000000000”,
“市场价值”:空
}],
“名称”:“农产品和蔬菜”
}]
};
var createBody=true;
变量$table=$('');
变量$thead=$('');
变量$tbody=$('');
var$水头=$('');
var$parentCells=null;
var columnHeaders=[];
$table.append($thead);
var$resultContainer=createResultsTable(resultFromWebService);
$(“#resultablecontainer”).append($resultContainer);
//$('#myTable').dataTable();
函数createResultsTable(数据、标题){
如果(数据){/&&data.length>0){
if(createBody){
$thead.append($headlow);
$table.append($tbody);
createBody=false;
}
如果(data.length>0){
addColumnHeader(数据[0]);
$。每个(数据,函数(索引,e){
可推广(e);
});
}否则{
添加列标题(数据);
可普及(数据);
}
}否则{
这个。noResults();
}
函数addColumnHeaders(结果){
for(结果中的var属性){
变量类型=结果的类型[属性];
如果(类型=='string'| |类型=='number'| |类型=='boolean'| | |结果[属性]日期实例| |!结果[属性]){
var maintentityname=result.\uuuuu元数据?result.\uuuu元数据.type.split(“.”)splice(-1)[0]+“:”;
mainEntityName=(标题?标题+”:mainEntityName);
var cName=maintentityname+属性;
if($.inArray(cName,ColumnHeader)<0){
$headlow.append($(''){
文本:cName
}));
columnHeaders.push(cName);
console.log(“columnHeader:+cName”);
}
}
}
}
函数populateTable(数据){
var$bodyRow=null;
如果($parentCells){
$bodyRow=$parentCells.clone();
}否则{
$bodyRow=$('');
}
var expandedChildResults=[];
$.each(数据、函数(索引、属性){
var类型=属性的类型;
如果(类型=='string'| |类型=='number'| |类型=='boolean'){
$bodyRow.append($(''){
文本:属性
}));
}else if(property instanceof Date){//DataJS将日期作为对象而不是字符串返回。
$bodyRow.append($(''){
text:property.toDateString()
}));
}如果(!属性){
$bodyRow.append(“”);
}else if(typeof property==='object'&&property.results&&index!=='uuu元数据'){
expandedChildResults.push({
关键字:property.results,
值:索引
});
}else if(typeof property==='object'&&index!='\uuu metadata'&&index!='\uu deferred'&&&!isPropertyAnObjectWithJustSingle\uu deferred(property)){
expandedChildResults.push({
关键:财产,
值:索引
});
}
});
如果(expandedChildResults.length>0){
$.each(展开的ChildResults,函数(索引,childObject){
$parentCells=$bodyRow;
createResultsTable(childObject.key,childObject.value);
});
$parentCells=null;
}否则
$tbody.append($bodyRow);
console.log($bodyRow);
}
函数isPropertyAnObjectWithJustSingle__;deferred(属性){
var键;
返回typeof属性==='object'&&&//测试它是否为和对象
(keys=Object.keys(property)).length==1&&//测试它是否只有sible属性
键[0]=='\uu deferred';//测试该属性是否为'\uu deferred'
}
返回$table;
};
最大的问题/总结

我遇到的问题是,一旦构建了整个表对象,我不确定如何将空单元格添加到行中,否则jquerydatable将不喜欢它

更新

var resultFromWebService = {
  //"odata.metadata": "http://localhost:21088/WcfDataService1.svc/$metadata#Categories&$select=Name,Products,Products/Currency/Symbol",
  "value": [{
    "Products": [],
    "Name": "Meat"
  }, {
    "Products": [{
      "Currency": {
        "ID": 47,
        "Num": 826,
        "Code": "GBP",
        "Description": "United Kingdom Pound",
        "DigitsAfterDecimal": 2,
        "Symbol": "\u00a3",
        "Hide": null,
        "Priority": 1
      },
      "ID": 2425,
      "Name": "303783",
      "ExpiryDate": "2014-02-22T00:00:00",
      "CurrencyID": 47,
      "Sales": "0.00000000000000000000",
      "PreTaxProfitOnProduct": null,
      "Assets": "0.30000000000000000000",
      "BarCode": null,
      "Worth": "0.20000000000000000000",
      "MarketValue": null
    }],
    "Name": "Produce & Vegetable"
  }]
};


var createBody = true;
var $table = $('<table id="myTable" class="defaultResultsFormatting"/>');
var $thead = $('<thead />');
var $tbody = $('<tbody />');
var $headRow = $('<tr/>');
var $parentCells = null;
var columnHeaders = [];
$table.append($thead);
var $resultContainer = createResultsTable(resultFromWebService);
$("#resultTableContainer").append($resultContainer);

//$('#myTable').dataTable();

function createResultsTable(data, title) {
  if (data) { // && data.length > 0) {
    if (createBody) {
      $thead.append($headRow);
      $table.append($tbody);
      createBody = false;
    }
    if (data.length > 0) {
      addColumnHeaders(data[0]);
      $.each(data, function(index, e) {
        populateTable(e);
      });
    } else {
      addColumnHeaders(data);
      populateTable(data);
    }
  } else {
    this.noResults();
  }

  function addColumnHeaders(result) {
    for (var property in result) {
      var type = typeof result[property];
      if (type === 'string' || type === 'number' || type === 'boolean' || result[property] instanceof Date || !result[property]) {
        var mainEntityName = result.__metadata ? result.__metadata.type.split(".").splice(-1)[0] + "." : "";
        mainEntityName = (title ? title + "." : mainEntityName);
        var cName = mainEntityName + property;
        if ($.inArray(cName, columnHeaders) < 0) {
          $headRow.append($('<th />', {
            text: cName
          }));
          columnHeaders.push(cName);
          console.log("columnHeader:" + cName);
        }
      }
    }
  }

  function populateTable(data) {
    var $bodyRow = null;
    if ($parentCells) {
      $bodyRow = $parentCells.clone();
    } else {
      $bodyRow = $('<tr/>');
    }

    var expandedChildResults = [];
    $.each(data, function(index, property) {
      var type = typeof property;
      if (type === 'string' || type === 'number' || type === 'boolean') {
        $bodyRow.append($('<td />', {
          text: property
        }));
      } else if (property instanceof Date) { // DataJS returns the dates as objects and not as strings.
        $bodyRow.append($('<td />', {
          text: property.toDateString()
        }));
      } else if (!property) {
        $bodyRow.append('<td />');
      } else if (typeof property === 'object' && property.results && index !== '__metadata') {
        expandedChildResults.push({
          key: property.results,
          value: index
        });
      } else if (typeof property === 'object' && index !== '__metadata' && index !== '__deferred' && !isPropertyAnObjectWithJustSingle__deferred(property)) {
        expandedChildResults.push({
          key: property,
          value: index
        });
      }
    });

    if (expandedChildResults.length > 0) {
      $.each(expandedChildResults, function(index, childObject) {
        $parentCells = $bodyRow;
        createResultsTable(childObject.key, childObject.value);
      });
      $parentCells = null;
    } else
      $tbody.append($bodyRow);
      console.log($bodyRow);
  }

  function isPropertyAnObjectWithJustSingle__deferred(property) {
    var keys;
    return typeof property === 'object' && // test if it's and object
      (keys = Object.keys(property)).length === 1 && // test if it has just sibgle property
      keys[0] === '__deferred'; // test if that property is '__deferred'
  }

  return $table;
};
当我有超过1个嵌套的子数组时,当前的答案不起作用,以此类推

正如你所看到的,只有一行,我希望它显示3行,就像我在这把小提琴中看到的一样


解决方案:)一旦您构建了表格,请调用另一个函数,该函数将通过向行中添加缺少的单元格来完成表格

这一逻辑必须有所帮助

function RestructureTheDynamicTable(){
 var $table = $('#myTable');
 var maxColumns = $table.find('thead tr th').length;    //find the total columns required

  $table.find('tbody tr').each(function(){
    var thisRowColumnCount = $(this).find('td').length;
    var extraTds = "";
    if(maxColumns > thisRowColumnCount){    //if this row doesn't have the required number of columns lets add them
      for(var i=0;i < maxColumns - thisRowColumnCount;i++){
        extraTds += "<td></td>";
      }
      $(this).append(extraTds);
    }    
  });
}
函数重构动态表(){
var$table=$(“#myTable”);
var maxColumns=$table.find('thead tr th').length;//查找所需的总列数
$table.find('tbody tr')。每个(函数(){
var thisRowColumnCount=$(this).find('td').length;
var extraTds=