最好用的 JSON 数据转化为表格结构的工具之一。
经过一系列的打磨之后,可以说 json5-to-table
是目前最方便的将 JSON 数据转化为表格的工具之一。 它支持:
- 嵌套的 JSON 数据,包括任意深层次的数组、对象等。
- 内建支持生成 HTML、Excel 格式。
- 可定制表头。
- 方便扩展,使用原生的
generateTable
函数可辅助生成任意格式。 - 提供一个命令行工具可用于跨语言的开发。
推荐使用 Yarn 或 NPM 安装:
// With Yarn
$ yarn add json5-to-table
// Or with NPM
$ npm install json5-to-table
亦可全局安装为了使用命令行工具:
// Global install with Yarn
$ yarn global add json5-to-table
// Or global install with NPM
$ npm install --global json5-to-table
也可以在浏览器内添加一个 script 标签(请替换 0.1.x 为正确的版本,发布的版本可在 Releases 中查看):
<script lang="javascript" src="https://github.com/yetrun/json5-to-table/releases/download/0.1.x/json5-to-table.js"></script>
默认支持生成 HTML 格式。如果需要生成 Excel 格式,需同时安装依赖包:
$ yarn add xlsx
如果是通过 Yarn 或 NPM 安装,使用 CommonJS 或 ES6 语法引入函数,例如
import {
generateTable,
generateHTMLTable,
generateExcel,
parseDataToSchema
} from 'json5-to-table'
如果是在浏览器中使用,使用全局变量 JSON5_TO_TABLE
:
const {
generateTable,
generateHTMLTable,
generateExcel,
parseDataToSchema
} = JSON5_TO_TABLE
然后调用函数生成表格结构,例如以下是生成 HTML 格式的表格:
const data = [
{
name: 'Jim',
age: 18,
courses: [
{ name: 'Music', duration: '3 hours' },
{ name: 'Basketball', duration: '2 hours' }
]
},
{
name: 'Lucy',
age: 17,
courses: [
{ name: 'Music', duration: '2 hours' },
{ name: 'Painting', duration: '2 hours and 30 minutes' },
{ name: 'Yoga', duration: '1 hour and 40 minutes' }
]
}
]
const schema = [
{ title: 'Name', path: 'name' },
{ title: 'Age', path: 'age' },
{ title: 'Courses', path: 'courses', props: [
{ title: 'Course Name', path: 'name' },
{ title: 'Learning Duration', path: 'duration' }
] }
]
generateHTMLTable(data, schema)
如此生成的表格的样子如下:
Name | Age | Courses | |
---|---|---|---|
Course Name | Learning Duration | ||
Jim | 18 | Music | 3 hours |
Basketball | 2 hours | ||
Lucy | 17 | Music | 2 hours |
Painting | 2 hours and 30 minutes | ||
Yoga | 1 hour and 40 minutes |
全局安装包以后,即可使用命令行工具 json5-to-table
. 其用法如下:
// 查看帮助文档
$ json5-to-table -h
// 生成 HTML 格式的表格,表格输出到控制台
$ json5-to-table -d <data-file> -e <schema-file> -p <options-file>
// 生成 Excel 格式的表格,表格输出到控制台
$ json5-to-table -d <data-file> --excel
使用场景
- 可作为工具使用,通过命令行的方式生成 HTML 或 Excel 表格。
- 其支持管道,可接入到其他语言。
特别说明
-
文件支持 JSON5 格式。
-
<data-file>
支持 All In One 格式。当不指定<schema-file>
和<options-file>
时,且<data-file>
的内容是以下结构,则从<data-file>
中获得data
、schema
、options
:// <data-file> 内容 { "data": [ // ... ], "schema": [ // ... ], "options": { // ... } }
-
当
<data-file>
参数未指定时,从标准输入中读取内容。
现有一段数据:
const data = [
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 }
]
我希望只对字段 a
、b
生成表格,过滤调字段 c
,这时可以用 Schema. Schema 的定义如下:
const schema = [
{ path: 'a' },
{ path: 'b' }
]
此时再调用 generateHTMLTable(data, schema)
,生成的表头将如下:
a | b |
---|
同样是以上的数据,我们希望以大写的 A 和 B 来显示表头,可通过配置 title
选项来实现:
const schema = [
{ title: 'A', path: 'a' },
{ title: 'B', path: 'b' }
]
除了常规的文本之外,title
还有以下两种特殊用法:
- 当
title
未给出时,文本由path
导出。例如{ path: 'a' }
和{ title: 'a', path: 'a' }
等价。 - 当
title
等于空白字符串时, 但表头不占用行单元格。 借助这个特性,可实现标量数组的分行显示。具体可参见将长文本数组分行显示。
path
用于定制该列提取数据的路径,它其实支持多种用法,列举如下:
''
:提取完整的数据。'a'
:提取字段a
.'a.b.c'
:依次提取字段a
、b
、c
,中间能很好地处理数组。
如果数据含有深层嵌套,这时可通过 props
选项定制深层的 schema
. 一个示例如下:
const data = [
{ a: 1, b: { c: 2, d: 3 }},
{ a: 4, b: { c: 5, d: 6 }}
]
const schema = [
{ path: 'a' },
{ path: 'b', props: [
{ path: 'c' },
{ path: 'd' }
] }
]
此时再调用 generateHTMLTable(data, schema)
,表头将展现嵌套格式:
a | b | |
---|---|---|
c | d |
在生成表格时,数组和对象不区分对待,对象可以看作含有当个元素的数组。为了理解如此,现举几个例子加以说明。
对于下面两个数据,它们生成的表格结构是一样的:
const data1 = { a: 1, b: 2, c: 3 }
const data2 = [
{ a: 1, b: 2, c: 3 }
]
即使内部字段是数组,它们的生成格式保持一致:
const data1 = [
{ a: 1, b: { c: 2, d: 3 } }
]
const data2 = [
{ a: 1, b: [
{ c: 2, d: 3 }
]}
]
下面用例子说明数组如何显示。首先给定内部含有两个元素的数组(字段 b
):
const data = [
{ a: 1, b: [
{ c: 2, d: 3 },
{ c: 4, d: 5 }
]}
]
给定 Schema:
const schema = [
{ path: 'a' },
{ path: 'b', props: [
{ path: 'c' },
{ path: 'd' }
]}
]
生成的完整表格显示为:
a | b | |
---|---|---|
c | d | |
1 | 2 | 3 |
4 | 5 |
任何生成表格结构的函数,包括 generateTable
、generateHTMLTable
、generateExcel
都包含两种用法:
-
显示指定 Schema,例如:
generateHTMLTable(data, schema)
-
隐式推导 Schema,例如:
generateHTMLTable(data, null, { parseDataToSchema: 'stack' })
这里讲一下两种推导的方式:stack
和 flatten
. 他们的区别在于如何处理嵌套表头。给出一条带嵌套的数据:
const data = [
{
a: 1,
b: {
c: 2, d: 3
}
}
]
使用 stack
生成的表头是:
generateHTMLTable(data, null, { parseDataToSchema: 'stack' })
a | b | |
---|---|---|
d |
使用 flatten
生成的表头是:
generateHTMLTable(data, null, { parseDataToSchema: 'stack' })
a | b.c | b.d |
---|
默认使用的策略是 stack
,也就是说
generateHTMLTable(data)
等效于
generateHTMLTable(data, null, { parseDataToSchema: 'stack' })
虽然可以使用隐式推导,但我这里还是不推荐使用,最主要的原因是无法保证列的顺序。例如对于以下数据:
const data = [
{ a: 1, b: 2, c: 3 },
{ c: 4, b: 5, a: 6 }
]
无法保证列一定按照 a
、b
、c
的顺序排列。 一方面依赖于浏览器的实现, 另一方面推导算法也不做任何保证。
因此一律推荐在任何时候显示地指定 Schema. 如果你对 Schema 不够了解,可通过 parseDataToSchema
函数先导出 Schema,再调整成自身需要的样子。详细技巧可参见使用 parseDataToSchema 了解 Schema 的用法。
定义
generateTable(data, schema, options)
描述
该函数生成的表格格式以 JS 对象表示,其主要作用是提供一种方便的中间格式,以便转化为其他格式。实质上,generateHTMLTable
和 generateExcel
都是基于该函数快速开发出来的。
参数解释
data
:任意 JavaScript 数据,包括数组、对象、数字、字符串、Null、Undefined 等。schema
:定制表头结构,其用法在前文有详细讲解。options
:选项对象,当前仅支持一个选项:parseSchemaToData
:"stack"
或"flatten"
.
示例
const data = [
{
a: 1,
b: [
{ c: 2, d: 3 }
]
},
{
a: 4,
b: [
{ c: 5, d: 6 },
{ c: 7, d: 8 }
]
}
]
const schema = [
{ path: 'a' },
{ path: 'b', props: [
{ path: 'c' },
{ path: 'd' }
] }
]
generateTable(data, schema)
显示输出为:
{
header: [
[
{ row: 1, col: 1, val: 'a', rowSpan: 2, colSpan: 1 },
{ row: 1, col: 2, val: 'b', rowSpan: 1, colSpan: 2 },
undefined
],
[
undefined,
{ row: 2, col: 2, val: 'c', rowSpan: 1, colSpan: 1 },
{ row: 2, col: 3, val: 'd', rowSpan: 1, colSpan: 1 }
]
],
body: [
[
{ row: 3, col: 1, val: 1, rowSpan: 1, colSpan: 1 },
{ row: 3, col: 2, val: 2, rowSpan: 1, colSpan: 1 },
{ row: 3, col: 3, val: 3, rowSpan: 1, colSpan: 1 }
],
[
{ row: 4, col: 1, val: 4, rowSpan: 2, colSpan: 1 },
{ row: 4, col: 2, val: 5, rowSpan: 1, colSpan: 1 },
{ row: 4, col: 3, val: 6, rowSpan: 1, colSpan: 1 }
],
[
undefined,
{ row: 5, col: 2, val: 7, rowSpan: 1, colSpan: 1 },
{ row: 5, col: 3, val: 8, rowSpan: 1, colSpan: 1 }
]
]
}
定义
generateHTMLTable(data, schema, options)
作用
生成 HTML 表格源码,返回的格式是字符串。生成的 HTML 表格用到的标签包括 <table>
、<thead>
、<tbody>
、<tr>
、<th>
、<td>
,可为标签定制属性,包括 class
、style
及其他。
参数解释
data
和schema
:同generateTable
.options
:选项对象,除了支持generateTable
的选项之外,还支持下列选项:attributes
: 声明标签用到的属性,具体用法看示例。
示例
// 添加标签属性
generateHTMLTable(data, schema, {
attributes: {
table: { class: 'c-table' },
thead: { class: 'c-table-header' },
tbody: { class: 'c-table-body' },
tr: { class: 'c-table-row' },
'thead.tr': { style: 'background: light-blue' },
'tbody.tr': { style: 'background: cyan' },
th: { class: 'c-header-cell' },
td: { class: 'c-data-cell' }
}
})
备注
需同时安装依赖包 xlsx
.
定义
generateExcel(data, schema, options)
作用
生成 Excel 表格。
参数解释
data
和schema
:同generateTable
.options
:选项对象,除了支持generateTable
的选项之外,还支持下列选项:writeTo
: 一个文件路径。
示例
// 写入到文件路径
generateExcel(data, schema, { writeTo: '/tmp/example.xlsx' })
// 写入到标准输出
generateExcel(data, schema, { writeTo: '/dev/stdout' })
定义
parseDataToSchema(data, mode)
作用
通过数据推导出 Schema,支持两种推导方式。
参数解释
data
:数据mode
:推导方式,支持两种推导方式"stack"
和"flatten"
. 其详细区别可参考数据推导表格部分。
虽然很少见, 但如果我们遇到下面的数组数据:
const data = ['A', 'B', 'C']
默认情况下显示在一个格子里:
A,B,C |
我们希望对他分行显示,这时可通过定制空白的 path
满足目的:
const schema = { title: 'Data', path: '' }
显示效果将是:
Data |
---|
A |
B |
C |
数组在单元格中显示文本使用的是 array.toString()
方法,[1, 2, 3]
的显示效果是 1,2,3
. 如果遇到长文本数组,例如:
const data = {
short: 1,
long: [
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
]
}
默认的显示方式将不够好。这时可通过定制 Schema 来实现数组的分行显示:
const schema = [
{ path: 'short' },
{ path: 'long', props: [
{ title: '', path: '' }
]}
]
显示效果将如下:
short | long |
---|---|
1 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB | |
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC |
解释
这里用到 title
和 path
的特殊用法。空字符串的 title
不占用表头的格子,空字符串的 path
提取完整数据。由于数据是数组,所以改为提取数组内的完整数据。
有些同学刚开始可能不知道 Schema 的用法,这时可通过 parseDataToSchema
推导出 Schema 并在控制台打印出来,打印出来的结果可调整以满足自己的需要。
import { generateHTMLTable, parseDataToSchema } from '@yetrun/json-to-table'
const data = [
// ...
]
// 查看 Schema
console.log(parseDataToSchema(data))
// 从控制台复制 Schema,并根据自己的需要调整
const schema = [
// ...
]
// 显式应用 Schema 并生成表格
generateHTMLTable(data, schema)
可提交 PR 以改进本项目,亦可克隆源码进行二次开发。这里列出开发时常用到的命令:
# 运行单元测试
$ yarn test
# 构建和打包
$ yarn build