-1

我试图弄清楚如何解析我在使用 vanilla javascript 调用特定数据库(如下所示的 JSON 响应)时收到的 JSON 响应 - 到目前为止,我还没有运气。我正在对 Quickbase 数据库进行 API 调用,它们的 JSON 响应具有标准格式。我正在调用的 API 可以在此链接中找到:https ://developer.quickbase.com/operation/runQuery 。

这是来自 API 调用的响应的样子

{
    "data": [
        {
            "6": {
                "value": 11.0
            },
            "69": {
                "value": "A"
            },
            "70": {
                "value": "B"
            }
        },
        {
            "6": {
                "value": 11.0
            },
            "69": {
                "value": "C"
            },
            "70": {
                "value": "D"
            }
        }
    ],
    "fields": [
        {
            "id": 6,
            "label": "Related Invoice",
            "type": "numeric"
        },
        {
            "id": 69,
            "label": "TEST1",
            "type": "text"
        },
        {
            "id": 70,
            "label": "TEST2",
            "type": "text"
        }
    ],
    "metadata": {
        "numFields": 3,
        "numRecords": 2,
        "skip": 0,
        "totalRecords": 2
    }
}

这就是我想要将其解析成的内容(不需要省略此处未显示的 JSON - 为了清楚起见,我只是这样做了)

{
    "data": [
        {
            "Related Invoice":11.0,
            "TEST1":"A",
            "TEST2":"B"
        },
        {
            "Related Invoice":11.0,
            "TEST1":"C",
            "TEST2":"D"
        }
    ]
}

下面是我正在使用的完整 javascript 代码

let headers = {
    'QB-Realm-Hostname': 'XXXXXX',
        'User-Agent': 'Invoice',
    'Authorization': 'XXXXXX',
    'Content-Type': 'application/json'
}

let body = 

{
  "from": "bq2paydp2",
  "select": [
    6,
    69,
    70
  ],
  "where": "{6.EX.11}",
  "sortBy": [
    {
      "fieldId": 6,
      "order": "ASC"
    },
    {
      "fieldId": 69,
      "order": "ASC"
    }
  ]
}


const xmlHttp = new XMLHttpRequest();
xmlHttp.open('POST', 'https://api.quickbase.com/v1/records/query', true);
for (const key in headers) {
  xmlHttp.setRequestHeader(key, headers[key]);
}
xmlHttp.onreadystatechange = function() {
  if (xmlHttp.readyState === XMLHttpRequest.DONE) {
    console.log(xmlHttp.responseText);


let line_items = JSON.parse(this.responseText, dataReviver);

console.log(line_items);

//function dataReviver (key, value) {
//if (key = 6)
//  {
//      var newHeaderName = 99;
//      return newHeaderName;
//  }
//
//  return value;
//} 


//document.getElementById('abc').innerHTML =  line_items.data[0][6].value;
   
function generateTableHead(table,tableData) {
  let thead = table.createTHead();
  let row = thead.insertRow();
  for (let key of tableData) {
    let th = document.createElement("th");
    let text = document.createTextNode(key);
    th.appendChild(text);
    row.appendChild(th);
  }
};

function generateTable(table, tableData) {
  for (let element of tableData) {
    let row = table.insertRow();
    for (key in element) {
      let cell = row.insertCell();
      let text = document.createTextNode(element[key]);
      cell.appendChild(text);
    }
  }
};


let table = document.querySelector("table");
let tableData = Object.keys(line_items.data[0]);
generateTableHead(table, tableData);
generateTable(table, line_items.data);

  }
};


xmlHttp.send(JSON.stringify(body));

这就是我想要实现的目标

|-----------------------------------------|
| Count | Related Invoice | TEST1 | TEST2 |
|-------|-----------------|-------|-------|
|   1   |       11.0      |   A   |   B   |
|-------|-----------------|-------|-------|      
|   2   |       11.0      |   C   |   D   |
|-----------------------------------------|

我需要完成三件事:

  • #1 重命名"6", "69 and "70"为对应的fields.label( "Related Invoice", "TEST1" and "TEST2")。
  • #2 将嵌套在上面#1 所示对象下的对象11.0, "A", "B", ...的值( ) 设置为上面#1 所示对象的值。例如,这将6 (Related Invoice)生成键和11.0值。
  • #3 我最终想在网页上的表格中显示它。html 和 css 我可以处理我不太擅长的 Javascript 和 JSON。

如果您需要我澄清更多信息,请告诉我。

4

1 回答 1

1

要以您正在查看的方式转换数据,您需要循环data对象中的键并根据循环结果创建一个新数组。

一种方法是使用Array.prototype.map(). 有了这个,您可以遍历数组中的每个项目并返回一个新值。

在此映射循环中,您将遍历data数组中的每个项目。对于每个项目,您需要从数组中获取idand并使用该数组创建一个新对象。要在循环中创建新对象,您可以使用该方法。labelfieldsArray.prototype.reduce()

因此,在这种情况下,您将有一个嵌套循环。内部循环将遍历fields数组并使用 id 从data数组中获取正确的值。然后它返回一个对象,其中包含您请求label的集合。value然后,周围的map方法将返回一个包含对象的新数组。多多,魔法!

const response = {
  "data": [{
      "6": {
        "value": 11.0
      },
      "69": {
        "value": "A"
      },
      "70": {
        "value": "B"
      }
    },
    {
      "6": {
        "value": 11.0
      },
      "69": {
        "value": "C"
      },
      "70": {
        "value": "D"
      }
    }
  ],
  "fields": [{
      "id": 6,
      "label": "Related Invoice",
      "type": "numeric"
    },
    {
      "id": 69,
      "label": "TEST1",
      "type": "text"
    },
    {
      "id": 70,
      "label": "TEST2",
      "type": "text"
    }
  ],
  "metadata": {
    "numFields": 3,
    "numRecords": 2,
    "skip": 0,
    "totalRecords": 2
  }
};

const transformResponseData = (response) => {
  const { data, fields } = response;

  // Return a new array with objects based on the values
  // of the data and fields arrays.
  const revivedData = data.map(entry =>
    fields.reduce((object, { id, label }) => {
      object[label] = entry[id].value;
      return object;
    }, {})
  );

  // Combine the original object with the new data key.
  return {
    ...response,
    data: revivedData
  };
};

const createTable = ({ data, fields }) => {
  const table = document.createElement('table');
  const tHead = table.createTHead();
  const tBody = table.createTBody();

  
  const tHeadRow = tHead.insertRow();
  
  // Create the counts cell manually.
  const tHeadRowCountCell = document.createElement('th');
  tHeadRowCountCell.textContent = 'Count';
  tHeadRow.append(tHeadRowCountCell);
    
  // Create a head for each label in the fields array.
  for (const { label } of fields) {
    const tHeadRowCell = document.createElement('th');
    tHeadRowCell.textContent = label;
    tHeadRow.append(tHeadRowCell);
  }

  // Output all the values of the new data array.
  for (const [index, entry] of data.entries()) {
    const tBodyRow = tBody.insertRow();
    
    // Create a new array with the index and the
    // values from the object.
    const values = [
      index + 1,
      ...Object.values(entry)
    ];

    // Loop over the combined values array.
    for (const [index, value] of values.entries()) {
      const tBodyCell = tBodyRow.insertCell();
      tBodyCell.textContent = index === 1 ?
        value.toFixed(1) :
        value;
    }
  }

  return table;
};

const data = transformResponseData(response);
const table = createTable(data);
document.body.append(table);

于 2021-03-22T08:54:24.290 回答