【问题标题】:CSV File object to JSON in AngularCSV文件对象到Angular中的JSON
【发布时间】:2021-11-04 16:35:01
【问题描述】:

在我的应用程序的前端,我想解析一些与他们上传的 CSV 相关的数据。通过文件上传工具,我先得到一个FileList对象,然后把1个文件拉出来。

我想把它变成一个 json 对象,然后我可以对其进行迭代。我正在考虑从节点使用 csv-parser,但我没有看到利用存储在内存中的 File 对象的方法。

我怎样才能做到这一点?

一开始我在做:

let f = fileList.item(0);
let decoder = new window.TextDecoder('utf-8');
f.arrayBuffer().then( data => {
   let _data = decoder.decode(data)
   console.log("Dataset", data, _data)
});

那是传递数组缓冲区,并解码字符串。虽然我可以编写一个通用工具来处理基于 \n 和 '' 的字符串数据,但我希望它更易于阅读。

我想做这样的事情:

let json = csvParser(f)

有没有办法从节点(3.0.0)使用 csv-parser 或者我应该利用其他工具?我在想利用基于浏览器的模块( new window.TextDecoder(...) )是糟糕的形式,因为它有可能失败。

有这样的工具吗?我试图创建一些示例数据并给定一个从输入 type="file" 中挑选的文件,我希望它简单明了。

下面的这个例子有效,但我觉得窗口依赖和直觉让我觉得这很幼稚。

const f : File = fileList.item(0)
console.log("[FOO] File", f)
let decoder = new window.TextDecoder('utf-8');
f.arrayBuffer().then( data => {
    let _data = decoder.decode(data)
    console.log("Dataset", data, _data)
    let lines = _data.split("\n")
    let headers = lines[0].split(',')
    let results = []
    for ( let i = 1; i < lines.length; i++) {
        let line = lines[i]
        let row = {}
        line.split(",").forEach( (item, idx) => {
            row[headers[idx]] = item;
        })
        results.push(row)
    }
    console.log("JSON ARRAY", results)
})

我停止并执行时运行的问题:ng serve 是它不喜欢使用 arrayBuffer 函数并从窗口访问 TextDecoder,因为在构建过程中,thost 函数/类分别不是 File 和 window 的一部分。

有什么想法吗?

【问题讨论】:

    标签: json angular typescript csv


    【解决方案1】:

    这就是我最终要做的,因为文件输入被传递到这个函数中:

    updateTranscoders(project: Project, fileList: FileList, choice: string = 'replace') {
        const f: File = fileList.item(0)
            //Reads a File into a string.
            function readToString(file) : Promise<any> {
                const reader = new FileReader();
                const future = new Promise( (resolve,reject) => {
                    reader.addEventListener("load", () => {
                        resolve(reader.result);
                    }, false)
                    reader.addEventListener("error", (event) => {
                        console.error("ERROR", event)
                        reject(event)
                    }, false)
                    reader.readAsText(file)
                }); 
                return future;
            }
            readToString(f).then( data => {
                let lines = data.split("\n")
                let headers = lines[0].split(',')
                let results = []
                for (let i = 1; i < lines.length; i++) {
                    let line = lines[i]
                    let row = {}
                    line.split(",").forEach((item, idx) => {
                        row[headers[idx]] = item;
                    })
                    results.push(row)
                }
                if (choice.toLowerCase() === 'replace'){
                    let rows = project.csvListContents.toJson().rows.filter( row => row.isDeployed)
                    rows.push( ...results)
                    project.csvListContents = CsvDataset.fromJson({ rows: rows })
                }else if (choice.toLowerCase() === 'append') {
                    let r = project.csvListContents.toJson();
                    r.rows.push(...results);
                    project.csvListContents = CsvDataset.fromJson(r);
                }else {
                    alert("Invalid option for Choice.")
                }
                    
                this.saveProject(project)
            })
        }
    

    现在代码的 CHOICE 部分是我有一个二进制选项来对 CSV 内容进行硬替换或只是附加到它的地方。然后我会相应地保存项目。这也是理解第一行包含列标题。

    【讨论】:

      猜你喜欢
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-11
      • 2017-09-25
      • 2013-05-13
      • 1970-01-01
      相关资源
      最近更新 更多