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

JSON.stringify处理嵌套对象数组失效,返回空数组问题求助

JSON.stringify序列化时嵌套数组返回空数组的问题

我知道这个问题有人问过,但现有方案都无效,无法定位问题。我有一个包含嵌套对象数组的对象,使用JSON.stringify序列化时,嵌套数组返回空数组。

以下是构建对象的简化版本(原代码通过循环遍历行,此处手动创建两行):

// JAVASCRIPT
let obj = {};
obj['type'] = 'Setting';
obj['id'] = 1;
obj['import'] = parseCSV();

function parseCSV() {
    let jsonData = [];
    let row1 = {};
    let row2 = {};
    row1['date'] = '2022-01-01';
    row1['amount'] = '30';
    row2['date'] = '2022-01-02';
    row2['amount'] = '50';
    jsonData.push(row1);
    jsonData.push(row2);
    return jsonData;
}

console.log('RAW DATA', obj);
console.log('STRINGIFIED', JSON.stringify(obj));

该简化版本能输出正确的序列化JSON。

但完整版本中,import字段序列化后是空数组。问题出在parseCSV函数中,以下是完整的parseCSV函数:

function parseCSV(file) {
    let filename = file.name;
    let extension = filename.substring(filename.lastIndexOf('.')).toUpperCase();
    if(extension == '.CSV') {
        try {
            let reader = new FileReader();
            let jsonData = [];
            let headers = [];
            reader.readAsBinaryString(file);
            reader.onload = function(e) {
                let rows = e.target.result.split('\n');
                for(let i = 0; i < rows.length; i++) {
                    let cells = rows[i].split(',');
                    let rowData = {};
                    for(let j = 0; j < cells.length; j++) {
                        if(i == 0) headers.push(cells[j].trim());
                        else {
                            if(headers[j]) rowData[headers[j]] = cells[j].trim();
                        }
                    }
                    if(i != 0 && rowData['date'] != '') jsonData.push(rowData);
                }
            }
            return jsonData;
        } catch(err) {
            console.error('!! ERROR READING CSV FILE', err);
        }
    } else alert('PLEASE UPLOAD A VALID CSV FILE');
}

编辑:按照@BJRINT的建议在parseCSV前添加await时,出现语法错误await is only valid in async function,相关代码如下:

async function submitForm(event) {
    event.preventDefault();
    
    let newItem = await gatherFormData(event.target);
    
    return fetch('server.php', {
        method: "POST",
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        },
        body: JSON.stringify(newItem)
    })
    .then(checkError)
    .then(data => parseData(data))
    .catch(err => console.error('>> ERROR READING JSON DATA', err));
}

function gatherFormData(target) {
    const inputs = target.querySelectorAll('input');
    let obj = {};
    inputs.forEach(function(input) {
        if(intKeys.indexOf(input.name) >= 0) obj[input.name] = parseInt(input.value);
        else if(curKeys.indexOf(input.name) >= 0) obj[input.name] = parseInt(parseFloat(input.value) * 100);
        else if(chkKeys.indexOf(input.name) >= 0) input.checked ? obj[input.name] = 1 : obj[input.name] = 0;
        else if(fileKeys.indexOf(input.name) >= 0 && input.files.length > 0) obj[input.name] = parseCSV(input.files[0]);
        else obj[input.name] = input.value;
    });
    return obj;
}

问题原因及解决方案

问题根源

FileReader是异步操作,你的parseCSV函数在reader.onload回调执行前就返回了空的jsonData数组。等文件读取完成并填充数据时,函数早已返回,所以最终序列化的是空数组。

修复步骤

  1. 将parseCSV改为返回Promise,在文件读取完成并处理好数据后再返回结果;
  2. 将gatherFormData改为异步函数,调用parseCSV时使用await等待结果;
  3. 由于forEach不支持异步等待,将遍历逻辑改为for...of循环。

修改后的代码

修正后的parseCSV函数

function parseCSV(file) {
  return new Promise((resolve, reject) => {
    let filename = file.name;
    let extension = filename.substring(filename.lastIndexOf('.')).toUpperCase();
    if (extension === '.CSV') {
      try {
        const reader = new FileReader();
        let jsonData = [];
        let headers = [];
        
        reader.onload = function(e) {
          const rows = e.target.result.split('\n');
          for (let i = 0; i < rows.length; i++) {
            const cells = rows[i].split(',');
            const rowData = {};
            for (let j = 0; j < cells.length; j++) {
              if (i === 0) {
                headers.push(cells[j].trim());
              } else {
                if (headers[j]) {
                  rowData[headers[j]] = cells[j].trim();
                }
              }
            }
            if (i !== 0 && rowData['date'] !== '') {
              jsonData.push(rowData);
            }
          }
          resolve(jsonData);
        };
        
        reader.onerror = function(err) {
          console.error('!! ERROR READING CSV FILE', err);
          reject(err);
        };
        
        reader.readAsBinaryString(file);
      } catch (err) {
        console.error('!! ERROR READING CSV FILE', err);
        reject(err);
      }
    } else {
      const errorMsg = 'PLEASE UPLOAD A VALID CSV FILE';
      alert(errorMsg);
      reject(new Error(errorMsg));
    }
  });
}

修正后的gatherFormData函数

async function gatherFormData(target) {
  const inputs = target.querySelectorAll('input');
  let obj = {};
  
  // 使用for...of支持await
  for (const input of inputs) {
    if (intKeys.indexOf(input.name) >= 0) {
      obj[input.name] = parseInt(input.value);
    } else if (curKeys.indexOf(input.name) >= 0) {
      obj[input.name] = parseInt(parseFloat(input.value) * 100);
    } else if (chkKeys.indexOf(input.name) >= 0) {
      obj[input.name] = input.checked ? 1 : 0;
    } else if (fileKeys.indexOf(input.name) >= 0 && input.files.length > 0) {
      // await等待parseCSV完成
      obj[input.name] = await parseCSV(input.files[0]);
    } else {
      obj[input.name] = input.value;
    }
  }
  
  return obj;
}

这样修改后,gatherFormData会等待CSV文件读取并解析完成后再返回对象,JSON.stringify就能正确序列化包含数据的嵌套数组了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:05:23