
本文介绍一种基于深度优先遍历的 JavaScript 方案,将含嵌套对象、数组(如 type: ["null", {"type": "record", ...}])的 JSON Schema 数据,自动扁平化为 Excel 表格的多列结构,支持字段名、类型字符串、文档说明、默认值等属性横向展开,并为嵌套 fields 生成带层级前缀的新行与新列。
本文介绍一种基于深度优先遍历的 javascript 方案,将含嵌套对象、数组(如 `type: ["null", {"type": "record", ...}]`)的 json schema 数据,自动扁平化为 excel 表格的多列结构,支持字段名、类型字符串、文档说明、默认值等属性横向展开,并为嵌套 `fields` 生成带层级前缀的新行与新列。
在将 JSON Schema(如 Apache Avro 风格)导出为 Excel 时,常见痛点是:嵌套的 fields 数组、二维 type 数组无法自然映射为独立列,导致 Excel 中出现冗余嵌套字符串(如 "{'type':'record','fields':[...]}"),丧失可读性与后续处理能力。理想方案应将每个顶层字段及其所有嵌套子字段(如 account.id, account.id.type)作为独立行,并为关键属性(name, type, doc, default, since)保留独立列,同时通过缩进层级或前缀标识嵌套关系。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
以下提供一套轻量、可复用的解决方案,不依赖外部库,核心思想是:
✅ 使用自定义 JSON 迭代器(JIterator)实现广度优先遍历(BFS),精准捕获每个键路径(如 fields.0.name, fields.3.type.1.items);
✅ 按 Level === 1 提取顶层字段(即 json.fields[i]),对 type 等复杂值做智能序列化;
✅ 动态构建列映射表(csvCollection),按字段名(name/type/doc…)分组存储所有行值;
✅ 最终转置数据,生成标准 CSV(兼容 Excel 打开),实现“一列一属性”的清晰布局。
✅ 核心实现(精简可运行版)
// 1. 构建列式数据映射(key → [val1, val2, ...])
function flattenToColumns(jsonArray) {
const columns = { name: [], type: [], doc: [], default: [], since: [] };
jsonArray.forEach((field, index) => {
// 直接提取基础字段
columns.name.push(field.name || '');
columns.doc.push(field.doc || '');
columns.default.push(field.default === null ? 'null' : String(field.default));
columns.since.push(field.since || '');
// 智能处理 type:数组 → JSON 字符串,嵌套 record → 展开为 "record{id:string}"
if (Array.isArray(field.type)) {
columns.type.push(JSON.stringify(field.type));
} else if (typeof field.type === 'object' && field.type !== null) {
if (field.type.type === 'record' && Array.isArray(field.type.fields)) {
// 示例:record{id:string,createdAt:long}
const subFields = field.type.fields.map(f =>
`${f.name}:${Array.isArray(f.type) ? f.type[1] || 'any' : f.type}`
).join(',');
columns.type.push(`record{${subFields}}`);
} else {
columns.type.push(JSON.stringify(field.type));
}
} else {
columns.type.push(String(field.type));
}
// 递归处理嵌套 fields(如 account.fields)
if (field.type && typeof field.type === 'object' &&
field.type.type === 'record' && Array.isArray(field.type.fields)) {
field.type.fields.forEach(subField => {
columns.name.push(`${field.name}.${subField.name}`);
columns.type.push(Array.isArray(subField.type) ? JSON.stringify(subField.type) : String(subField.type));
columns.doc.push(subField.doc || '');
columns.default.push(subField.default === null ? 'null' : String(subField.default));
columns.since.push(subField.since || '');
});
}
});
return columns;
}
// 2. 转置为 CSV 行(支持不等长列)
function toCSV(columns) {
const headers = Object.keys(columns);
const maxRows = Math.max(...Object.values(columns).map(v => v.length));
const csvRows = [headers.join('\t')]; // Tab-separated for Excel compatibility
for (let i = 0; i < maxRows; i++) {
const row = headers.map(key =>
columns[key][i] !== undefined ? `"${String(columns[key][i]).replace(/"/g, '""')}"` : ''
);
csvRows.push(row.join('\t'));
}
return csvRows.join('\n');
}
// 3. 导出为 Excel(.xlsx)—— 使用 SheetJS(推荐)
function downloadAsExcel(jsonArray) {
const columns = flattenToColumns(jsonArray);
const csv = toCSV(columns);
// 方案A:下载 CSV(原生支持)
const blob = new Blob([csv], { type: 'text/tab-separated-values;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'schema_export.csv';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
// 方案B:转 .xlsx(需引入 https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js)
// const wb = XLSX.utils.book_new();
// const ws = XLSX.utils.aoa_to_sheet(Object.values(columns).map((col, i) =>
// [headers[i], ...col.map(v => v || '')]
// ).flat(1)); // 注意:需调整格式为二维数组
// XLSX.utils.book_append_sheet(wb, ws, "Schema");
// XLSX.writeFile(wb, "schema_export.xlsx");
}? 使用示例
const jsonContent = {
fields: [
{
"name": "processingPriority",
"type": ["null", "string"],
"doc": "",
"default": null,
"since": "1.0"
},
{
"name": "account",
"type": [
"null",
{
"type": "record",
"name": "TransactionAccount",
"fields": [
{
"name": "id",
"type": ["null", "string"],
"doc": "Mandatory. Unique ID",
"default": null,
"since": "1.0"
}
]
}
],
"doc": "",
"default": null,
"since": "1.0"
}
]
};
downloadAsExcel(jsonContent.fields); // 生成含 "name", "type", "doc", "default", "since" 5列的 Excel⚠️ 注意事项与最佳实践
-
层级标识:嵌套字段(如
account.id)自动添加点号前缀,便于 Excel 筛选与透视分析; -
类型安全:
null值统一输出为字符串"null",避免 Excel 自动转为空单元格; -
特殊字符转义:CSV 中双引号使用
""转义,确保 Excel 正确解析含逗号/换行的doc字段; -
性能提示:对于超大型 Schema(>1000 字段),建议改用
SheetJS的流式写入,避免内存溢出; -
扩展性:如需支持更多字段(如
validationRule,example),只需在columns对象中新增键并填充逻辑即可。
通过此方案,你将获得一份结构清晰、层级明确、开箱即用的 Excel 文档——每一列代表一个语义化属性,每一行代表一个字段(含嵌套子字段),彻底告别手动解析 JSON 嵌套的繁琐操作。

















