用更合理的方式写 E-JSON
- 规范的代码可以促进团队合作,
- 规范的代码可以减少
bug
处理, - 规范的代码可以降低维护成本,
- 规范的代码有助于代码审查,
- 养成代码规范的习惯,有助于程序员自身的成长。
简介
E-JSON
的设计目标是使业务系统向浏览器端传递的 JSON
数据保持一致,容易被理解和处理,并兼顾传输的数据量。E-JSON
依托于 http
协议(rfc2616
)与 JSON
数据交换格式(rfc4627
)。
要求
在本文档中,使用的关键字会以中文 括号包含的关键字英文表示:必须(MUST
)。关键字 "MUST
", "MUST NOT
", "REQUIRED
", "SHALL
", "SHALL NOT
", "SHOULD
", "SHOULD NOT
", "RECOMMENDED
", "MAY
", "OPTIONAL
"被定义在 rfc2119
中。
JSON数据类型
JSON(JavaScript Object Notation)
是一种轻量级,基于文本,语言无关的数据交换格式。其包括了基本数据类型 4
种和复合数据类型 2
种,共 6
种数据类型。在下面章节中,JSON
数据类型的表示法为 JSON
空格
数据类型
,如:JSON Array
。
传输的数据,包括对象属性以及数组成员, 必须(MUST) 是 6
种 JSON
数据类型之一。 杜绝(MUST NOT) 使用 function
、Date
等 js
对象类型。
基本数据类型
Number
可以表示整数和浮点数。Boolean
可以表示真假,值为true
或false
。String
表示一个字符串。Null
通常用于表示空对象。
"true"
和 true
,这两个数据代表的是不同的数据类型。非字符串类型数据输出时一定 不要(MUST NOT) 为两端加上双引号,否则可能产生不希望的后果(如 if
中判断 "false"
的结果是 true
)。其他容易产生错误的例子如:0
和 "0"
等。
复合数据类型
Object
是无序的集合,以键值对的方式保持数据。一个 Object
中包含零到多个 name/value
的数据,数据间以逗号(,)
分隔。name
为 String
类型,value
可以是任意类型的数据。
Object
的最后一个元素之后一定 不要(MUST NOT) 加上分隔符的逗号,否则可能导致解析出错。
Array(数组)
为多个值的有序集合,数组元素间以逗号(,)
分隔。
http响应头
status
http
响应的 status
必须(MUST) 为 200
。通常 JSON
数据被用于通过 XMLHttpRequest
对象访问,通过 javascript
进行处理。返回错误的状态码可能导致错误不被响应,数据不被处理。
Content-Type
Content-Type
字段定义了响应体的类型。一般情况下,浏览器会根据该类型对内容进行正确的处理。对于传输 JSON
数据的响应,Content-Type
推荐(RECOMMENDED) 设置为 "text/javascript"
或 "text/plain"
。 避免(MUST NOT) 将 Context-Type
设置为 text/html
,否则可能导致安全问题。
Content-Type
中可以指定字符集。通常 需要(SHOULD) 明确指定一个字符集。如果是通过 XMLHTTPRequest
请求的数据,并且字符编码为 UTF-8
时,可以不指定字符集。
Context-Type示例
代码语言:javascript复制text/javascript;charset=UTF-8
数据字段
返回的数据包含在 http
响应体中。数据 必须(MUST) 是一个 JSON Object
。该 Object
可能包含 3
个字段:status
,statusInfo
,data
。
status
status
字段 必须(MUST) 是一个不小于 0
的 JSON Number
整数,表示请求的状态。这个字段 可以(SHOULD) 被省略,省略时和为 0
时表示同一含义。
0
:表示 server
端理解了请求,成功处理并返回。
非 0
:表示发生错误。 可以(SHOULD) 根据错误类型扩展错误码。
一个成功请求的status字段
代码语言:javascript复制{
"status": 0,
"data": "hello world!"
}
statusInfo
statusInfo
字段 通常(SHOULD) 是一个 JSON String
或 JSON Object
,表示除了请求状态外 server
端想要对 status
做出的说明,使 client
端能够获取更多信息进行后续处理。这个字段是 可选的(OPTIONAL) 。下面的两个例子中,statusInfo
字段的信息都可以用于 client
端程序的后续处理,但是粒度和处理方式会有不同。
client端参数错误的statusInfo
简单说明的 statusInfo
:
{
"status": 1,
"statusInfo": "参数错误"
}
具有更多信息的 statusInfo
:
{
"status": 1,
"statusInfo": {
"text": "参数错误",
"parameters": {
"email": "电子邮件格式不正确"
}
}
}
data
data
字段可以是除 JSON Null
之外的任意 JSON
类型,表示请求返回的数据主体。这个字段是 可选的(OPTIONAL) 。数据主体 data
包含了在请求成功时有意义的数据。
一个查询姓名请求的返回数据
代码语言:javascript复制{
"status": 0,
"data": "Lily"
}
数据场景
本章为常见数据场景定义了通用的标准数据格式,用于数据传输和使用。额外地,本章为部分可能大数据量传输的数据场景定义了变通数据格式。变通数据格式可在数据解析阶段转换成标准数据格式。
变通数据格式 必须(MUST) 是一个 JSON Object
,其中 必须(MUST) 包含 e-type
属性和 data
属性。e-type
属性标识数据类型,便于对数据进行解析;data
属性包含变通后的数据。变通数据 可以(MAY) 包含其他的属性,标识数据的其他扩展信息。
变通数据格式的 e-type
属性定义了 table
值。e-type
属性可以使用者扩展其他属性值,扩展的属性值 必须(MUST) 以 “项目缩写-名称”
命名,如 “fc-list”
,自主解析。
日期类型
日期类型不属于 JSON
数据类型。对于日期类型,我们 必须(MUST) 使用 JSON String
来表示。为了让日期能够更容易的被显示和被解析,对于日期我们 应当(SHOULD) 使用更适合 internet
的格式,遵循 rfc3339
。
数据场景:日期
代码语言:javascript复制{
"status": 0,
"data": "2010-10-10"
}
记录
记录代表二维表中的一行,通常用于表示某个具体事务抽象的属性。标准记录数据 必须(MUST) 为一个 JSON Object
,记录的主键命名 必须(MUST) 为 “id”
。单条记录数据不包含变通数据格式。
数据场景:记录
代码语言:javascript复制{
"id": 250,
"name": "erik",
"sex": 1,
"age": 18
}
二维表
二维表类型表识为 table
,是关系模型的主要数据结构。二维表结构具有变通数据格式。标准二维表数据 必须(MUST) 以一维 JSON Array
形式表示,JSON Array
中每一项是一个 JSON Object
,代表一条记录。JSON Object
的每个成员代表一个字段。每条记录的主键命名 必须(MUST) 为 "id"
。
在标准二维表中,字段名在每条记录中都被传输,会造成额外的数据量传输。这个问题会随着记录数的增大会更加突出。为了减少传输数据量,变通格式使用二维 JSON Array
传输数据,扩展 fields
属性用于字段说明。fields
字段为 JSON Array
。
数据场景:标准二维表
代码语言:javascript复制[
{
"id": 250,
"name": "erik",
"sex": 1,
"age": 18
},
{
"id": 251,
"name": "欧阳先伟",
"sex": 1,
"age": 28
}
]
数据场景:变通二维表
代码语言:javascript复制{
"e-type": "table",
"fields": ["id", "name", "sex", "age"],
"data": [
[250, "erik", 1, 18],
[251, "欧阳先伟", 1, 28]
]
}
数据页
数据页是列表数据常用的数据方式,可能通过查询或翻页获得数据。数据页是二维表数据的包装,包含列表数据本身更多的信息。
数据页 必须(MUST) 是一个 JSON Object
,其中 必须(MUST) 包含的属性为 data
。data
是一个二维表。数据页可以包括一些 可选(OPTIONAL) 的属性,表示当前数据页的信息。下表列举了数据页的可选属性。
数据页可选属性
{Number} page
- 当前页码,计数 必须(MUST) 为不小于0
的整数,从0
开始。{Number} pageSize
- 每页显示条数, 必须(MUST) 大于0
。{Number} total
- 列表总记录数, 必须(MUST) 为不小于0
的整数。表示当前条件下所有记录的数目,非本页的记录数。{String} orderBy
- 列表排序规则。多个排序规则之间以逗号分割(,)
;正序或倒序以asc
或desc
表示,与字段名之间以一个空格间隔。例:"id desc,name asc"
{String} keyword
- 列表所属的搜索关键字。{Object} condition
- 列表所属的搜索条件集合。属性中可以包含或不包含keyword
字段,如果不包含, 建议(RECOMMMANDED) 在解析的时候附加搜索关键字keyword
条件。
数据场景:数据页
代码语言:javascript复制{
"page": 0,
"pageSize": 30,
"keyword": "",
"data": [
{
"id": 250,
"name": "erik",
"sex": 1,
"age": 18
},
{
"id": 251,
"name": "欧阳先伟",
"sex": 1,
"age": 28
}
]
}
键/值对象
对于在一个 JSON Object
中表示键/值:
- 键的属性名 必须(MUST) 为
name
, 杜绝(MUST NOT) 使用key
或k
- 值的属性名 必须(MUST) 为
value
, 杜绝(MUST NOT) 使用v
。
数据场景:键/值对象
代码语言:javascript复制{
"name": "BMW",
"value": 1
}
键/值有序集合
键/值有序集合表示对事务或逻辑类型的抽象与分类。常见的应用场景有单选复选框集合,下拉菜单等。
标准的键/值有序集合是一个 JSON Array
,集合中的每一项是一个 JSON Object
。项 必须(MUST) 包含 name
和 value
属性。 可以(MAY) 通过其他的属性修饰每一项的特殊信息,如 selected
。
数据场景:键/值有序集合
代码语言:javascript复制[
{
"name": "BMW",
"value": 1
},
{
"name": "Benz",
"value": 2,
"selected": true
}
]
树
树形数据用于表示层叠的数据结构。树型数据 必须(MUST) 是一个 JSON Object
,代表树型数据的根节点。下面是标准定义的可选节点列表,不在列表中的属性 可以(SHOULD) 自行扩展。
树型数据结构的可选节点属性
{Number|String} id
- 节点的唯一标识。{String} text
- 名称或用于显示的字符串。{Array} children
- 子节点列表。
数据场景:树型数据
代码语言:javascript复制{
"id": 1,
"text": "中国",
"children": [
{
"id": 10,
"text": "北京",
"children": [
{
"id": 100,
"text": "东城区"
},
{
"id": 101,
"text": "西城区"
},
{
"id": 102,
"text": "海淀区"
}
......
]
},
{
"id": 31,
"text": "海南",
"children": [
{
"id": 600,
"text": "海口"
},
{
"id": 601,
"text": "三亚"
},
{
"id": 602,
"text": "五指山"
}
......
]
}
......
]
}
引用
- [RFC 2119] "Key words for use in RFCs to Indicate Requirement Levels"
- [RFC 4627] "The application/json Media Type for JavaScript Object Notation (JSON)"
- [RFC 2616] "Hypertext Transfer Protocol"
- [RFC 3339] "Date and Time on the Internet: Timestamps"