Node.js读取文本生成指定JSON格式出错,求排查问题
排查Node.js生成目标JSON格式的代码问题
问题回顾
你想要把TSV(实际是CSV格式)文件里的每行数据转换成指定的JSON数组:每行开头的数字作为key,该行其余每个值单独对应一个{key: value}对象。
原始数据示例:
100004990,a122,a128,a169,a2122,a42474 100008935,a41661,a42189,a64407,a8199,a17031,a186,a25199
期望生成的JSON格式:
[{"100004990":"a122"},{"100004990":"a128"},{"100004990":"a169"},{"100004990":"a2122"},{"100004990":"a42474"},{"100008935":"a41661"},{"100008935":"a42189"},{"100008935":"a64407"},{"100008935":"a8199"},{"100008935":"a17031"},{"100008935":"a186"},{"100008935":"a25199"}]
但目前运行代码后,生成的JSON是空对象数组,控制台输出里的value全是undefined。
代码问题分析
我帮你梳理下代码里的几个关键问题:
- 循环条件错误:原代码里的
for (var i = 1; i <= row.length; i++)是核心问题。数组索引从0开始,row.length是该行元素的总数,当i等于row.length时,row[i]就不存在了,自然是undefined。比如第一行有6个元素,i从1到6,i=6时row[6]就是undefined,这就是控制台输出里出现大量undefined的原因。正确的条件应该是i < row.length,这样i从1遍历到row.length-1,正好取到所有的value元素。 - 对象复用导致的引用问题:你在forEach里定义了
tmp = {},然后在for循环里反复修改这个对象并push到数组。因为所有push的都是同一个对象的引用,最后数组里的对象都会是最后一次修改的结果。正确的做法是在for循环内部每次创建新的对象,而不是复用同一个tmp。 - 计数器写法无效:
x = x++是错误的写法,后置递增x++会先返回x的当前值再递增,所以这个赋值相当于x没有变化。直接写成x++或者x += 1就可以了。 - 同步读文件的冗余回调:
fs.readFileSync是同步方法,不需要传入回调函数,这个回调永远不会被执行,可以直接删掉。 - 空行未过滤:
split("\n")可能会产生空行(比如文件末尾的换行),导致后续split得到的row数组只有空元素,处理时会出错,建议提前过滤掉空行。
修复后的代码
// Node packages for file system var fs = require('fs'); var path = require('path'); var filePath = path.join(__dirname, 'dataservices_statsocial_raw.tsv'); // 同步读取文件,不需要回调 var f = fs.readFileSync(filePath, { encoding: 'utf-8' }); // 按行分割并过滤空行 f = f.split("\n").filter(line => line.trim() !== ''); console.log(f.length); var json = []; var x = 1; f.forEach(function(d) { console.log(x + "============"); var row = d.split(","); // 取第一个元素作为key var key = row[0]; // 遍历从第二个元素开始的所有value for (var i = 1; i < row.length; i++) { // 每次循环创建新的对象 var tmp = {}; tmp[key] = row[i]; json.push(tmp); } x++; // 修正计数器写法 }); console.log(json); var outPath = path.join(__dirname, 'new.json'); // 同步写入文件,不需要回调 fs.writeFileSync(outPath, JSON.stringify(json), 'utf8');
验证结果
运行修复后的代码后,控制台会输出正确的对象数组,生成的new.json文件内容会完全符合你期望的格式,每个value都对应一个独立的{key: value}对象。
内容的提问来源于stack exchange,提问作者user3872094
相关产品推荐
相关产品推荐

