簡體   English   中英

JSON.stringify 不適用於嵌套的對象數組

[英]JSON.stringify not working with nested array of objects

我知道有人問過這個問題,但沒有一個解決方案對我有用,我也不知道出了什么問題。 我有一個 object,其中包含我正在字符串化的嵌套對象數組,但是當我在其上使用 JSON.stringify 時,我得到了嵌套數組的空白數組。

這是我構建 object 的簡化版本。主要區別在於有一個 for 循環遍歷所有行,這里我只是手動創建 2 行

// 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 function 中的某個地方,因為當我使用上面的簡化版本時,我得到了正確的字符串化數據,但我無法查明我錯在哪里。 下面是我的完整 function。

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');*/
}

謝謝您的幫助!

編輯

當我在parseCSV之前添加await時,@BJRINT 的回答表明我收到語法錯誤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;
}

問題不是來自 stringify function。由於您正在異步填充數組(當執行讀取器回調時)但首先返回您的數據,因此它是空的。

你可以用 Promise 包裝你的 function ,當最終執行讀者回調 function 時解析,如下所示:

function parseCSV(file) {
    return new Promise((resolve, reject) => {
        let filename = file.name;
        let extension = filename.substring(filename.lastIndexOf('.')).toUpperCase();
        if(extension !== '.CSV') 
            return reject('PLEASE UPLOAD A VALID CSV FILE')

        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 resolve(jsonData);
            }
            
        } catch(err) {
            return reject('!! ERROR READING CSV FILE', err);
        }
    })
}


// calling the function
const data = await parseCSV(file)

適用於我的特定案例的解決方案是結合使用 BJRINT 的答案和計時器來繼續檢查我在此處找到的數據是否已完成加載。

async function parseCSV(file) {
    return await new Promise((resolve, reject) => {
        let extension = file.name.substring(file.name.lastIndexOf('.')).toUpperCase();
        if(extension !== '.CSV') reject('PLEASE UPLOAD A VALID CSV FILE');
        
        try {
            let reader = new FileReader();
            reader.readAsText(file);
            reader.onload = function(e) {
                let jsonData = [];
                let headers = [];
                let rows = e.target.result.split(/\r\n|\r|\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);
                }
                resolve(jsonData);
            }
        } catch(err) {
            reject(err);
        }
    });
}

function submitForm(event) {
    event.preventDefault();
    showForm(false);
    loading.classList.remove('hidden');
    
    let ready = true;
    const inputs = event.target.querySelectorAll('input');
    let newItem = {};
    
    let check = function() {
        if(ready === true) {
            console.log(newItem);
            console.log(JSON.stringify(newItem));
            
            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));
        }
        setTimeout(check, 1000);
    }
    
    inputs.forEach(function(input) {
        if(intKeys.indexOf(input.name) >= 0) newItem[input.name] = parseInt(input.value);
        else if(curKeys.indexOf(input.name) >= 0) newItem[input.name] = parseInt(parseFloat(input.value) * 100);
        else if(chkKeys.indexOf(input.name) >= 0) input.checked ? newItem[input.name] = 1 : newItem[input.name] = 0;
        else if(fileKeys.indexOf(input.name) >= 0 && input.files.length > 0) {
            ready = false;
            parseCSV(input.files[0]).then(data => {
                ready = true;
                newItem[input.name] = data;
            });
        }
        else newItem[input.name] = input.value;
    });
    
    check();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM