JS解析Excel后怎么将数据转换为JSON格式
详细讲解在JavaScript环境下解析Excel并将其转换为JSON格式的完整方案,涵盖SheetJS核心API、对象数组与二维数组转换、日期格式处理、空值填补及完整代码示例。
JavaScript 处理 Excel 数据流转与结构化转换实用指南
XLSX.utils.sheet_to_json(worksheet, options)。这一函数会遍历单元格坐标体系,依照表头映射生成键值对象数组或纯二维矩阵。
一、准备工作与解析前置步骤
在编写转换代码前,需要明确运行环境。无论是浏览器前端还是 Node.js 后端,底层逻辑都是一致的:将二进制文件流反序列化为内存中的 Workbook(工作簿)对象,进而选取具体的 Worksheet(工作表)。
目前前端与 Node.js 社区使用最广泛的库是 xlsx(即 SheetJS)。安装或引入方式如下:
// Node.js 环境安装与引用
npm install xlsx
const XLSX = require('xlsx');
// 或使用 ESM
import * as XLSX from 'xlsx';
// 浏览器端引入示例
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>
完成依赖准备后,整个解析并转为 JSON 的操作可以拆解为四个具体步骤:
二、提取工作簿与工作表对象
在进行 JSON 转换前,必须先获得有效的 worksheet 引用。以下是不同宿主环境获取文件流并生成 worksheet 的标准实现:
1. 浏览器环境:通过 FileReader 异步读取
在前端页面中,通常结合 <input type="file"> 监听用户的选取操作:
function handleFileChange(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
const data = new Uint8Array(e.target.result);
// 解析工作簿,保留日期类型避免被识别为浮点数字
const workbook = XLSX.read(data, { type: 'array', cellDates: true });
// 获取第一个工作表的名称与对应内容
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
// 执行后续 JSON 转换
const jsonData = XLSX.utils.sheet_to_json(worksheet);
console.log('转换完成的JSON数据:', jsonData);
};
reader.readAsArrayBuffer(file);
}
2. Node.js 环境:直接读取本地文件
const fs = require('fs');
const XLSX = require('xlsx');
// 同步读取文件 Buffer
const fileBuffer = fs.readFileSync('./data.xlsx');
const workbook = XLSX.read(fileBuffer, { type: 'buffer', cellDates: true });
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet);
console.log('Node端解析结果:', jsonData);
三、sheet_to_json 映射原理与三种转换模式
Excel 本质是一个以行列坐标(如 A1, B2)标识单元格的二维网格,而 JSON 是由键值对对象或嵌套数组组成的树状结构。XLSX.utils.sheet_to_json 的核心职责就是建立行列矩阵与数据属性之间的映射关系。
模式 1:默认对象数组(以首行作为 Key)
这是最符合日常业务需求的形式。只要表格第一行是规整的列名,直接调用 XLSX.utils.sheet_to_json(worksheet) 即可:
// 默认配置转换
const list = XLSX.utils.sheet_to_json(worksheet);
// 输出示例:
// [
// { "姓名": "李强", "部门": "研发中心", "薪资": 18500 },
// { "姓名": "王芳", "部门": "市场营销", "薪资": 16000 }
// ]
模式 2:纯二维数组(矩阵形态,设置 header: 1)
当表格没有固定的表头,或者存在多级复杂表头时,如果强行转为对象容易丢失层级信息。此时可以传入配置 { header: 1 },将工作表按行转换为纯二维数组:
// 转换为二维数组
const matrix = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
// 输出示例:
// [
// ["姓名", "部门", "薪资"],
// ["李强", "研发中心", 18500],
// ["王芳", "市场营销", 16000]
// ]
这种模式适用于读者后续需要根据索引自定义拼装数据、动态渲染虚拟表格或做矩阵运算的场景。
模式 3:自定义英文字段别名(指定 header 数组)
在前后端交互中,Excel 中的中文表头(如“姓名”、“年龄”)通常不能直接当作数据库或接口字段名。虽然可以在拿到 JSON 后二次遍历重命名,但直接在转换时指定 header 数组是更高效的做法:
// 传入自定义属性名数组
const userList = XLSX.utils.sheet_to_json(worksheet, {
header: ['userName', 'department', 'salary'],
range: 1 // 跳过原始表格中的第 1 行(即跳过中文表头所在的索引 0)
});
// 输出示例:
// [
// { userName: "李强", department: "研发中心", salary: 18500 },
// { userName: "王芳", department: "市场营销", salary: 16000 }
// ]
注意:设置自定义 header 数组时,必须同步配置 range: 1(或者根据实际情况跳过表头所在行数),否则第 1 行的中文标题也会被转换成一条数据记录。
四、实际应用中的关键细节与高频问题解决
很多初学者在写完基础调用后,会发现导出的 JSON 存在日期错误、空值键丢失或多余空白行等现象。以下是生产开发中最常遇到的四大细节及针对性处理手段:
1. 日期格式解析偏差:时间变成一串奇怪数字
现象:在 Excel 中填写的 2026-05-20,在转换为 JSON 后变成了类似 46162 的纯数字。
原因:Excel 底层将日期存储为基于基准日期(通常为 1900 年 1 月 1 日)的天数序列号。若未明确开启时间解析,SheetJS 会直接输出原始浮点数。
解决方法:在调用 XLSX.read 时显式配置 cellDates: true:
// 正确做法:开启 cellDates 参数
const workbook = XLSX.read(data, {
type: 'array',
cellDates: true // 自动将日期单元格转换为 JavaScript 原生 Date 对象
});
// 若需统一格式化为 "YYYY-MM-DD" 字符串,可在 sheet_to_json 中配合 dateNF 选项:
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
raw: false,
dateNF: 'yyyy-mm-dd'
});
2. 空单元格导致属性键缺失(对象结构不对齐)
现象:第 2 行的张三填写了“备注”,第 3 行的李四“备注”留空。转出来的 JSON 中,李四的对象里根本没有 备注 这个属性,导致后续前端使用 item.remark.trim() 时报 TypeError: Cannot read properties of undefined。
解决方法:设置 defval: ""(或 defval: null),强制补全缺失属性:
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
defval: '' // 缺失的单元格统一填充为空字符串
});
3. 表头空格与不可见字符清洗
制作 Excel 表格的人员经常会在表头中不小心敲入空格(如 " 姓名 " 或 "年 龄"),导致生成的 JSON Key 变成 { " 姓名 ": "张三" },给后续取值造成阻碍。如果表格是由第三方任意上传的,建议在转出后进行统一的 Key 清洗:
function sanitizeKeys(jsonArray) {
return jsonArray.map(row => {
const cleanRow = {};
for (const [key, value] of Object.entries(row)) {
// 去除表头首尾空白及常见多余符号
const cleanKey = key.trim();
cleanRow[cleanKey] = typeof value === 'string' ? value.trim() : value;
}
return cleanRow;
});
}
4. 过滤空行与无效数据
用户编辑 Excel 时,有时在下方误触敲击了空格或删除了内容,留下带有样式或空字符串的无效行。为了避免向后端传递无效对象,需增加一行数据有效性判定:
const rawList = XLSX.utils.sheet_to_json(worksheet, { defval: '' });
// 过滤掉所有字段均为空字符的“幽灵行”
const validList = rawList.filter(row => {
return Object.values(row).some(val => val !== '' && val !== null && val !== undefined);
});
五、浏览器端端到端完整可运行示例
下面是一个包含 HTML 上传输入框、状态提示及转换展示的完整独立示例。读者可将此代码保存为本地 .html 文件直接在浏览器双击验证效果:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Excel 转 JSON 运行示例</title>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>
</head>
<body>
<h3>选取 Excel 文件进行解析</h3>
<input type="file" id="excelInput" accept=".xlsx, .xls, .csv" />
<h4>输出 JSON 结果:</h4>
<pre id="outputResult" style="background: #f4f4f4; padding: 12px; border-radius: 4px;">等待上传文件...</pre>
<script>
const inputElement = document.getElementById('excelInput');
const outputElement = document.getElementById('outputResult');
inputElement.addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(event) {
try {
const buffer = new Uint8Array(event.target.result);
// 1. 读取工作簿,开启时间解析
const workbook = XLSX.read(buffer, { type: 'array', cellDates: true });
// 2. 选取第一张工作表
const sheetName = workbook.SheetNames[0];
const sheet = workbook.Sheets[sheetName];
// 3. 转换为 JSON,指定默认填充值
const jsonResult = XLSX.utils.sheet_to_json(sheet, {
defval: '',
raw: false,
dateNF: 'yyyy-mm-dd'
});
// 4. 展示在页面上
outputElement.textContent = JSON.stringify(jsonResult, null, 2);
} catch (err) {
outputElement.textContent = '解析失败:' + err.message;
}
};
reader.readAsArrayBuffer(file);
});
</script>
</body>
</html>
六、全流程要点与排坑决策总结
为了让读者在实际工程开发中快速排查与决策,下图总结了从 Excel 解析到 JSON 结构化过程中的关键决策链路与高频问题对应方案:
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JavaScript与Java有什么区别?核心特性对比
2026-11-04 20:45:10








