google JSON风格指南

原文连接:https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.mdjavascript

版本:0.9html

英文版:https://google.github.io/styleguide/jsoncstyleguide.xmljava

翻译:Darcy Liugit

译文状态:草稿github

简介

该风格指南是对在Google建立JSON APIs而提供的指导性准则和建议。整体来说,JSON APIs应遵循JSON.org上的规范。这份风格指南澄清和标准化了特定状况,从而使Google的JSON APIs有一种标准的外观和感受。这些指南适用于基于RPC和基于REST风格的API的JSON请求和响应。web

定义

为了更好地实现这份风格指南的目的,下面几项须要说明:apache

  • 属性(property) - JSON对象内的键值对(name/value pair)
  • 属性名(property name) - 属性的名称(或键)
  • 属性值(property value) - 分配给属性的值

示例:json

{
  // 一组键值对称做一个 "属性".
  "propertyName": "propertyValue"
}

Javascript的数字(number)包含全部的浮点数,这是一个宽泛的指定。在这份指南中,数字(number)指代Javascript中的数字(number)类型,而整型(integer)则指代整型。api

通常准则

注释

JSON对象中不包含注释。数组

JSON对象中不该该包含注释。该指南中的某些示例含有注释。但这仅仅是为了说明示例。

{
  // 你可能在下面的示例中看到注释,
  // 但不要在你的JSON数据中加入注释.
  "propertyName": "propertyValue"
}

双引号

使用双引号

若是(某个)属性须要引号,则必须使用双引号。全部的属性名必须在双引号内。字符类型的属性值必须使用双引号。其它类型值(如布尔或数字)不该该使用双引号。

扁平化数据 VS 结构层次

不能为了方便而将数据任意分组

JSON中的数据元素应以扁平化方式呈现。不能为了方便而将数据任意分组。

在某些状况下,好比描述单一结构的一批属性,由于它被用来保持结构层次,于是是有意义的。可是遇到这些状况仍是应当慎重考虑,记住只有语义上有意义的时候才使用它。例如,一个地址能够有表示两种方式,但结构化的方式对开发人员来说可能更有意义:

扁平化地址:

{
  "company": "Google",
  "website": "http://www.google.com/",
  "addressLine1": "111 8th Ave",
  "addressLine2": "4th Floor",
  "state": "NY",
  "city": "New York",
  "zip": "10011"
}

结构化地址:

{
  "company": "Google",
  "website": "http://www.google.com/",
  "address": {
    "line1": "111 8th Ave",
    "line2": "4th Floor",
    "state": "NY",
    "city": "New York",
    "zip": "10011"
  }
}

属性名准则

属性名格式

选择有意义的属性名

属性名必须遵循如下准则:

  • 属性名应该是具备定义语义的有意义的名称。
  • 属性名必须是驼峰式的,ASCII码字符串。
  • 首字符必须是字母,下划线(_)或美圆符号($)。
  • 随后的其余字符能够是字母,数字,下划线(_)或美圆符号($)。
  • 应该避免使用Javascript中的保留关键字(下文附有Javascript保留字清单)

这些准则反映JavaScript标识符命名的指导方针。使JavaScript的客户端可使用点符号来访问属性。(例如, result.thisIsAnInstanceVariable).

下面是一个对象的一个属性的例子:

{
  "thisPropertyIsAnIdentifier": "identifier value"
}

JSON Map中的键名

在JSON Map中键名可使用任意Unicode字符

当JSON对象做为Map(映射)使用时,属性的名称命名规则并不适用。Map(也称做关联数组)是一个具备任意键/值对的数据类型,这些键/值对经过特定的键来访问相应的值。JSON对象和JSON Map在运行时看起来是同样的;这个特性与API设计相关。当JSON对象被看成map使用时,API文件应当作出说明。

Map的键名不必定要遵循属性名称的命名准则。键名能够包含任意的Unicode字符。客户端可以使用maps熟悉的方括号来访问这些属性。(例如result.thumbnails["72"]

{
  // "address" 属性是一个子对象
  // 包含地址的各部分.
  "address": {
    "addressLine1": "123 Anystreet",
    "city": "Anytown",
    "state": "XX",
    "zip": "00000"
  },
  // "address" 是一个映射
  // 含有响应规格所对应的URL,用来映射thumbnail url的像素规格
  "thumbnails": {
    "72": "http://url.to.72px.thumbnail",
    "144": "http://url.to.144px.thumbnail"
  }
}

保留的属性名称

某些属性名称会被保留以便能在多个服务间相容使用

保留属性名称的详细信息,连同完整的列表,可在本指南后面的内容中找到。服务应按照被定义的语义来使用属性名称。

单数属性名 VS 复数属性名

数组类型应该是复数属性名。其它属性名都应该是单数。

数组一般包含多个条目,复数属性名就反映了这点。在下面这个保留名称中能够看到例子。属性名items是复数由于它描述的是一组对象。大多数的其它字段是单数。

固然也有例外,尤为是涉及到数字的属性值的时候。例如,在保留属性名中,totalItemstotalItem更合理。而后,从技术上讲,这并不违反风格指南,由于 totalItems 能够被看做 totalOfItems, 其中 total 是单数(依照风格指南),OfItems 用来限定总数。字段名也可被改成 itemCount,这样看起来更象单数.

{
  // 单数
  "author": "lisa",
  // 一组同胞, 复数
  "siblings": [ "bart", "maggie"],
  // "totalItem" 看起来并不对
  "totalItems": 10,
  // 但 "itemCount" 要好些
  "itemCount": 10
}

命名冲突

经过选择新的属性名或将API版本化来避免命名冲突

新的属性可在未来被添加进保留列表中。JSON中不存在命名空间。若是存在命名冲突,可经过选择新的属性名或者版本化来解决这个问题。例如,假设咱们由下面的JSON对象开始:

{
  "apiVersion": "1.0",
  "data": {
    "recipeName": "pizza",
    "ingredients": ["tomatoes", "cheese", "sausage"]
  }
}

若是咱们但愿未来把ingredients列为保留字,咱们能够经过下面两件事情来达成:

1.选一个不一样的名字

{
  "apiVersion": "1.0",
  "data": {
    "recipeName": "pizza",
    "ingredientsData": "Some new property",
    "ingredients": ["tomatoes", "cheese", "sausage"]
  }
}

2.在主版本上从新命名属性

{
  "apiVersion": "2.0",
  "data": {
    "recipeName": "pizza",
    "ingredients": "Some new property",
    "recipeIngredients": ["tomatos", "cheese", "sausage"]
  }
}

属性值准则

属性值格式

属性值必须是Unicode 的 booleans(布尔), 数字(numbers), 字符串(strings), 对象(objects), 数组(arrays), 或 null.

JSON.org上的标准准确地说明了哪些类型的数据能够做为属性值。这包含Unicode的布尔(booleans), 数字(numbers), 字符串(strings), 对象(objects), 数组(arrays), 或 null。JavaScript表达式是不被接受的。APIs应该支持该准则,并为某个特定的属性选择最合适的数据类型(好比,用numbers表明numbers等)。

好的例子:

{
  "canPigsFly": null,     // null
  "areWeThereYet": false, // boolean
  "answerToLife": 42,     // number
  "name": "Bart",         // string
  "moreData": {},         // object
  "things": []            // array
}

很差的例子:

{
  "aVariableName": aVariableName,         // Bad - JavaScript 标识符
  "functionFoo": function() { return 1; } // Bad - JavaScript 函数
}

空或Null 属性值

考虑移除空或null值

若是一个属性是可选的或者包含空值或null值,考虑从JSON中去掉该属性,除非它的存在有很强的语义缘由。

{
  "volume": 10,

  // 即便 "balance" 属性值是零, 它也应当被保留,
  // 由于 "0" 表示 "均衡" 
  // "-1" 表示左倾斜和"+1" 表示右倾斜
  "balance": 0,

  // "currentlyPlaying" 是null的时候可被移除
  // "currentlyPlaying": null
}

枚举值

枚举值应当以字符串的形式呈现

随着APIs的发展,枚举值可能被添加,移除或者改变。将枚举值看成字符串可使下游用户幽雅地处理枚举值的变动。

Java代码:

public enum Color {
  WHITE,
  BLACK,
  RED,
  YELLOW,
  BLUE
}

JSON对象:

{
  "color": "WHITE"
}

属性值数据类型

上面提到,属性值必须是布尔(booleans), 数字(numbers), 字符串(strings), 对象(objects), 数组(arrays), 或 null. 然而在处理某些值时,定义一组标准的数据类型是很是有用的。这些数据类型必须始终是字符串,可是为了便于解析,它们也会以特定的方式被格式化。

日期属性值

日期应该使用RFC3339建议的格式

日期应该是RFC 3339所建议的字符串格式。

{
  "lastUpdate": "2007-11-06T16:34:41.000Z"
}

时间间隔属性值

时间间隔应该使用ISO 8601建议的格式

时间间隔应该是ISO 8601所建议的字符串格式。

{
  // 三年, 6个月, 4天, 12小时,
  // 三十分钟, 5秒
  "duration": "P3Y6M4DT12H30M5S"
}

纬度/经度属性值

纬度/经度应该使用ISO 6709建议的格式

纬度/经度应该是ISO 6709所建议的字符串格式。 并且, 它应该更偏好使用 e ±DD.DDDD±DDD.DDDD 角度格式.

{
  // 自由女神像的纬度/经度位置.
  "statueOfLiberty": "+40.6894-074.0447"
}

JSON结构和保留属性名

为了使APIs保持一致的借口,JSON对象应当使用如下的结构。该结构适用于JSON的请求和响应。在这个结构中,某些属性名将被保留用做特殊用途。这些属性并非必需的,也就是说,每一个保留的属性可能出现零次或一次。可是若是服务须要这些属性,建议遵循该命名条约。下面是一份JSON结构语义表,以Orderly格式呈现(如今已经被归入 JSONSchema)。你能够在该指南的最后找到关于JSON结构的例子。

object {
  string apiVersion?;
  string context?;
  string id?;
  string method?;
  object {
    string id?
  }* params?;
  object {
    string kind?;
    string fields?;
    string etag?;
    string id?;
    string lang?;
    string updated?; # date formatted RFC 3339
    boolean deleted?;
    integer currentItemCount?;
    integer itemsPerPage?;
    integer startIndex?;
    integer totalItems?;
    integer pageIndex?;
    integer totalPages?;
    string pageLinkTemplate /^https?:/ ?;
    object {}* next?;
    string nextLink?;
    object {}* previous?;
    string previousLink?;
    object {}* self?;
    string selfLink?;
    object {}* edit?;
    string editLink?;
    array [
      object {}*;
    ] items?;
  }* data?;
  object {
    integer code?;
    string message?;
    array [
      object {
        string domain?;
        string reason?;
        string message?;
        string location?;
        string locationType?;
        string extendedHelp?;
        string sendReport?;
      }*;
    ] errors?;
  }* error?;
}*;

JSON对象有一些顶级属性,而后是data对象或error对象,这二者不会同时出现。下面是这些属性的解释。

顶级保留属性名称

顶级的JSON对象可能包含下面这些属性

apiVersion

属性值类型: 字符串(string)
父节点: -

呈现请求中服务API指望的版本,以及在响应中保存的服务API版本。应随时提供apiVersion。这与数据的版本无关。将数据版本化应该经过其余的机制来处理,如etag。

示例:

{ "apiVersion": "2.1" }

context

属性值类型: 字符串(string)
父节点: -

客户端设置这个值,服务器经过数据做出回应。这在JSON-P和批处理中颇有用,用户可使用context将响应与请求关联起来。该属性是顶级属性,由于无论响应是成功仍是有错误,context总应当被呈现出来。context不一样于id在于context由用户提供而id由服务分配。

示例:

请求 #1:

http://www.google.com/myapi?context=bart

请求 #2:

http://www.google.com/myapi?context=lisa

响应 #1:

{
  "context": "bart",
  "data": {
    "items": []
  }
}

响应 #2:

{
  "context": "lisa",
  "data": {
    "items": []
  }
}

公共的JavaScript处理器经过编码同时处理如下两个响应:

function handleResponse(response) {
  if (response.result.context == "bart") {
    // 更新页面中的 "Bart" 部分。
  } else if (response.result.context == "lisa") {
    // 更新页面中的 "Lisa" 部分。
  }
}

id

属性值类型: 字符串(string)
父节点: -

服务提供用于识别响应的标识(不管请求是成功仍是有错误)。这对于将服务日志和单独收到的响应对应起来颇有用。

示例:

{ "id": "1" }

method

属性值类型: 字符串(string)
父节点: -

表示对数据即将执行,或已被执行的操做。在JSON请求的状况下,method属性能够用来指明对数据进行何种操做。在JSON响应的状况下,method属性代表对数据进行了何种操做。

一个JSON-RPC请求的例子,其中method属性表示要在params上执行的操做:

{
  "method": "people.get",
  "params": {
    "userId": "@me",
    "groupId": "@self"
  }
}

params

属性值类型: 对象(object)
父节点: -

这个对象做为输入参数的映射发送给RPC请求。它能够和method属性一块儿用来执行RPC功能。若RPC方法不须要参数,则能够省略该属性。

示例:

{
  "method": "people.get",
  "params": {
    "userId": "@me",
    "groupId": "@self"
  }
}

data

属性值类型: 对象(object)
父节点: -

包含响应的全部数据。该属性自己拥有许多保留属性名,下面会有相应的说明。服务能够自由地将本身的数据添加到这个对象。一个JSON响应要么应当包含一个data对象,要么应当包含error对象,但不能二者都包含。若是dataerror同时出现,则error对象优先。

error

属性值类型: 对象(object)
父节点: -

代表错误发生,提供错误的详细信息。错误的格式支持从服务返回一个或多个错误。一个JSON响应能够有一个data对象或者一个error对象,但不能二者都包含。若是dataerror都出现,error对象优先。

示例:

{
  "apiVersion": "2.0",
  "error": {
    "code": 404,
    "message": "File Not Found",
    "errors": [{
      "domain": "Calendar",
      "reason": "ResourceNotFoundException",
      "message": "File Not Found
    }]
  }
}

data对象的保留属性名

JSON对象的data属性可能包含如下属性。

data.kind

属性值类型: 字符串(sting)
父节点: data

kind属性是对某个特定的对象存储何种类型的信息的指南。能够把它放在data层次,或items的层次,或其它任何有助于区分各种对象的对象中。若是kind对象被提供,它应该是对象的第一个属性(详见下面的属性顺序部分)。

示例:

// "Kind" indicates an "album" in the Picasa API.
{"data": {"kind": "album"}}

data.fields

属性值类型: 字符串(string)
父节点: data

表示作了部分GET以后响应中出现的字段,或作了部分PATCH以后出如今请求中的字段。该属性仅在作了部分GET请求/批处理时存在,且不能为空。

示例:

{
  "data": {
    "kind": "user",
    "fields": "author,id",
    "id": "bart",
    "author": "Bart"
  }
}

data.etag

属性值类型: 字符串(string)
父节点: data

响应时提供etag。关于GData APIs中的ETags详情能够在这里找到:http://code.google.com/apis/gdata/docs/2.0/reference.html#ResourceVersioning

示例:

{"data": {"etag": "W/"C0QBRXcycSp7ImA9WxRVFUk.""}}

data.id

属性值类型: 字符串(string)
父节点: data

一个全局惟一标识符用于引用该对象。id属性的具体细节都留给了服务。

示例:

{"data": {"id": "12345"}}

data.lang

属性值类型: 字符串(string)(格式由BCP 47指定)
父节点: data (或任何子元素)

表示该对象内其余属性的语言。该属性模拟HTML的lang属性和XML的xml:lang属性。值应该是BCP 47中定义的一种语言值。若是一个单一的JSON对象包含的数据有多种语言,服务负责制定和标明lang属性的适当位置。

示例:

{"data": {
  "items": [
    { "lang": "en",
      "title": "Hello world!" },
    { "lang": "fr",
      "title": "Bonjour monde!" }
  ]}
}

data.updated

属性值类型: 字符串(string)(格式由RFC 3339指定)
父节点: data

指明条目更新的最后日期/时间(RFC 3339),由服务规定。

示例:

{"data": {"updated": "2007-11-06T16:34:41.000Z"}}

data.deleted

属性值类型: 布尔(boolean)
父节点: data (或任何子元素)

一个标记元素,当出现时,表示包含的条目已被删除。若是提供了删除属性,它的值必须为true;为false会致使混乱,应该避免。

示例:

{"data": {
  "items": [
    { "title": "A deleted entry",
      "deleted": true
    }
  ]}
}

data.items

属性值类型: 数组(array)
父节点: data

属性名items被保留用做表示一组条目(例如,Picasa中的图片,YouTube中的视频)。这种结构的目的是给与当前结果相关的集合提供一个标准位置。例如,知道页面上的items是数组,JSON输出即可能插入一个通用的分页系统。若是items存在,它应该是data对象的最后一个属性。(详见下面的属性顺序部分)。

示例:

{
  "data": {
    "items": [
      { /* Object #1 */ },
      { /* Object #2 */ },
      ...
    ]
  }
}

用于分页的保留属性名

下面的属性位于data对象中,用来给一列数据分页。一些语言和概念是从OpenSearch规范中借鉴过来的。

下面的分页数据容许各类风格的分页,包括:

  • 上一页/下一页 - 容许用户在列表中前进和后退,一次一页。nextLinkpreviousLink属性 (下面的"连接保留属性名"部分有描述) 用于这种风格的分页。
  • 基于索引的分页 - 容许用户直接跳到条目列表的某个条目位置。例如,要从第200个条目开始载入10个新的条目,开发者能够给用户提供一个URL的查询字符串?startIndex=200
  • 基于页面的分页 - 容许用户直接跳到条目内的具体页。这跟基于索引的分页很相似,但节省了开发者额外的步骤,不需再为新一页的条目计算条目索引。例如,开发人员能够直接跳到第20页,而不是跳到第200条条目。基于页面分页的网址,可使用查询字符串?page=1?page=20pageIndextotalPages 属性用做这种风格的分页.

在这份指南的最后能够找到如何使用这些属性来实现分页的例子。

data.currentItemCount

属性值类型: 整数(integer)
父节点: data

结果集中的条目数目。应该与items.length相等,并做为一个便利属性提供。例如,假设开发者请求一组搜索条目,而且要求每页10条。查询集共有14条。第一个条目页将会有10个条目,所以itemsPerPagecurrentItemCount都应该等于10。下一页的条目还剩下4条;itemsPerPage仍然是10,可是currentItemCount是4.

示例:

{
  "data": {
    // "itemsPerPage" 不须要与 "currentItemCount" 匹配
    "itemsPerPage": 10,
    "currentItemCount": 4
  }
}

data.itemsPerPage

属性值类型: 整数(integer)
父节点: data

items结果的数目。未必是data.items数组的大小;若是咱们查看的是最后一页,data.items的大小可能小于itemsPerPage。可是,data.items的大小不该超过itemsPerPage

示例:

{
  "data": {
    "itemsPerPage": 10
  }
}

data.startIndex

属性值类型: 整数(integer)
父节点: data

data.items中第一个条目的索引。为了一致,startIndex应从1开始。例如,第一组items中第一条的startIndex应该是1。若是用户请求下一组数据,startIndex多是10。

示例:

{
  "data": {
    "startIndex": 1
  }
}

data.totalItems

属性值类型: 整数(integer)
父节点: data

当前集合中可用的总条目数。例如,若是用户有100篇博客文章,响应可能只包含10篇,可是totalItems应该是100。

示例:

{
  "data": {
    "totalItems": 100
  }
}

data.pagingLinkTemplate

属性值类型: 字符串(string)
父节点: data

URL模板指出用户能够如何计算随后的分页连接。URL模板中也包含一些保留变量名:表示要载入的条目的{index},和要载入的页面的{pageIndex}

示例:

{
  "data": {
    "pagingLinkTemplate": "http://www.google.com/search/hl=en&q=chicago+style+pizza&start={index}&sa=N"
  }
}

data.pageIndex

属性值类型: 整数(integer)
父节点: data

条目的当前页索引。为了一致,pageIndex应从1开始。例如,第一页的pageIndex是1。pageIndex也能够经过基于条目的分页而计算出来pageIndex = floor(startIndex / itemsPerPage) + 1

示例:

{
  "data": {
    "pageIndex": 1
  }
}

data.totalPages

属性值类型: 整数(integer)
父节点: data

当前结果集中的总页数。totalPages也能够经过上面基于条目的分页属性计算出来: totalPages = ceiling(totalItems / itemsPerPage).

示例:

{
  "data": {
    "totalPages": 50
  }
}

用于连接的保留属性名

下面的属性位于data对象中,用来表示对其余资源的引用。有两种形式的连接属性:1)对象,它能够包含任何种类的引用(好比JSON-RPC对象),2)URL字符串,表示资源的URIs(后缀总为'Link')。

data.self / data.selfLink

属性值类型: 对象(object)/字符串(string)
父节点: data

自身连接能够用于取回条目数据。好比,在用户的Picasa相册中,条目中的每一个相册对象都会包含一个selfLink用于检索这个相册的相关数据。

示例:

{
  "data": {
    "self": { },
    "selfLink": "http://www.google.com/feeds/album/1234"
  }
}

data.edit / data.editLink

属性值类型: 对象(object)/字符串(string)
父节点: data

编辑连接代表用户能够发送更新或删除请求。这对于REST风格的APIs颇有用。该连接仅在用户可以更新和删除该条目时提供。

示例:

{
  "data": {
    "edit": { },
    "editLink": "http://www.google.com/feeds/album/1234/edit"
  }
}

data.next / data.nextLink

属性值类型: 对象(object)/字符串(string)
父节点: data

该下一页连接标明如何取得更多数据。它指明载入下一组数据的位置。它能够同itemsPerPagestartIndextotalItems 属性一块儿使用用于分页数据。

示例:

{
  "data": {
    "next": { },
    "nextLink": "http://www.google.com/feeds/album/1234/next"
  }
}

data.previous / data.previousLink

属性值类型: 对象(object)/字符串(string)
父节点: data

该上一页连接标明如何取得更多数据。它指明载入上一组数据的位置。它能够连同itemsPerPagestartIndextotalItems 属性用于分页数据。

示例:

{
  "data": {
    "previous": { },
    "previousLink": "http://www.google.com/feeds/album/1234/next"
  }
}

错误对象中的保留属性名

JSON对象的error属性应包含如下属性。

error.code

属性值类型: 整数(integer)
父节点: error

表示该错误的编号。这个属性一般表示HTTP响应码。若是存在多个错误,code应为第一个出错的错误码。

示例:

{
  "error":{
    "code": 404
  }
}

error.message

属性值类型: 字符串(string)
父节点: error

一我的类可读的信息,提供有关错误的详细信息。若是存在多个错误,message应为第一个错误的错误信息。

示例:

{
  "error":{
    "message": "File Not Found"
  }
}

error.errors

属性值类型: 数组(array)
父节点: error

包含关于错误的附加信息。若是服务返回多个错误。errors数组中的每一个元素表示一个不一样的错误。

示例:

{ "error": { "errors": [] } }

error.errors[].domain

属性值类型: 字符串(string)
父节点: error.errors

服务抛出该错误的惟一识别符。它帮助区分服务的从普通协议错误(如,找不到文件)中区分出具体错误(例如,给日历插入事件的错误)。

示例:

{
  "error":{
    "errors": [{"domain": "Calendar"}]
  }
}

error.errors[].reason

属性值类型: 字符串(string)
父节点: error.errors

该错误的惟一识别符。不一样于error.code属性,它不是HTTP响应码。

示例:

{
  "error":{
    "errors": [{"reason": "ResourceNotFoundException"}]
  }
}

error.errors[].message

属性值类型: 字符串(string)
父节点: error.errors

一我的类可读的信息,提供有关错误的更多细节。若是只有一个错误,该字段应该与error.message匹配。

示例:

{
  "error":{
    "code": 404
    "message": "File Not Found",
    "errors": [{"message": "File Not Found"}]
  }
}

error.errors[].location

属性值类型: 字符串(string)
父节点: error.errors

错误发生的位置(根据locationType字段解释该值)。

示例:

{
  "error":{
    "errors": [{"location": ""}]
  }
}

error.errors[].locationType

属性值类型: 字符串(string)
父节点: error.errors

标明如何解释location属性。

示例:

{
  "error":{
    "errors": [{"locationType": ""}]
  }
}

error.errors[].extendedHelp

属性值类型: 字符串(string)
父节点: error.errors

help text的URI,使错误更易于理解。

示例:(注:原示例这里有笔误,中文版这里作了校订)

{
  "error":{
    "errors": [{"extendedHelp": "http://url.to.more.details.example.com/"}]
  }
}

error.errors[].sendReport

属性值类型: 字符串(string)
父节点: error.errors

report form的URI,服务用它来收集错误状态的数据。该URL会预先载入描述请求的参数

示例:

{
  "error":{
    "errors": [{"sendReport": "http://report.example.com/"}]
  }
}

属性顺序

在JSON对象中属性可有任意顺序。然而,在某些状况下,有序的属性能够帮助分析器快速解释数据,并带来更好的性能。在移动环境下的解析器就是个例子,在这种状况下,性能和内存是相当重要的,没必要要的解析也应尽可能避免。

Kind属性

Kind属性应为第一属性

假设一个解析器负责将一个原始JSON流解析成一个特定的对象。kind属性会引导解析器将适合的对象实例化。于是它应该是JSON对象的第一个属性。这仅适用于对象有一个kind属性的状况(一般能够在dataitems属性中找到)。

Items属性

items应该是data对象的最后一个属性

这使得阅读每个具体条目前前已读全部的集合属性。在有不少条目的状况下,这样就避免了开发人员只须要从数据的字段时没必要要的解析这些条目。

这让阅读全部集合属性先于阅读单个条目。如遇多个条目的状况,当开发者仅须要数据中的字段时,这就可避免解析没必要要的条目。

属性顺序示例:

// "kind" 属性区分 "album" 和 "photo".
// "Kind" 始终是它父对象的第一个属性.
// "items" 属性是 "data" 对象的最后一个属性.
{
  "data": {
    "kind": "album",
    "title": "My Photo Album",
    "description": "An album in the user's account",
    "items": [
      {
        "kind": "photo",
        "title": "My First Photo"
      }
    ]
  }
}

示例

YouTube JSON API

这是YouTube JSON API响应对象的示例。你能够从中学到更多关于YouTube JSON API的内容:http://code.google.com/apis/youtube/2.0/developers_guide_jsonc.html

{
  "apiVersion": "2.0",
  "data": {
    "updated": "2010-02-04T19:29:54.001Z",
    "totalItems": 6741,
    "startIndex": 1,
    "itemsPerPage": 1,
    "items": [
      {
        "id": "BGODurRfVv4",
        "uploaded": "2009-11-17T20:10:06.000Z",
        "updated": "2010-02-04T06:25:57.000Z",
        "uploader": "docchat",
        "category": "Animals",
        "title": "From service dog to SURFice dog",
        "description": "Surf dog Ricochets inspirational video ...",
        "tags": [
          "Surf dog",
          "dog surfing",
          "dog",
          "golden retriever",
        ],
        "thumbnail": {
          "default": "http://i.ytimg.com/vi/BGODurRfVv4/default.jpg",
          "hqDefault": "http://i.ytimg.com/vi/BGODurRfVv4/hqdefault.jpg"
        },
        "player": {
          "default": "http://www.youtube.com/watch?v=BGODurRfVv4&feature=youtube_gdata",
          "mobile": "http://m.youtube.com/details?v=BGODurRfVv4"
        },
        "content": {
          "1": "rtsp://v5.cache6.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
          "5": "http://www.youtube.com/v/BGODurRfVv4?f=videos&app=youtube_gdata",
          "6": "rtsp://v7.cache7.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp"
        },
        "duration": 315,
        "rating": 4.96,
        "ratingCount": 2043,
        "viewCount": 1781691,
        "favoriteCount": 3363,
        "commentCount": 1007,
        "commentsAllowed": true
      }
    ]
  }
}

分页示例

如何将Google搜索条目做为JSON对象展示出来,对分页变量也有特别关注。

这个示例仅用做说明。下面的API实际上并不存在。

这是Google搜索结果页面的示例: image

image

这是该页面JSON形式的呈现:

{
  "apiVersion": "2.1",
  "id": "1",
  "data": {
    "query": "chicago style pizza",
    "time": "0.1",
    "currentItemCount": 10,
    "itemsPerPage": 10,
    "startIndex": 11,
    "totalItems": 2700000,
    "nextLink": "http://www.google.com/search?hl=en&q=chicago+style+pizza&start=20&sa=N"
    "previousLink": "http://www.google.com/search?hl=en&q=chicago+style+pizza&start=0&sa=N",
    "pagingLinkTemplate": "http://www.google.com/search/hl=en&q=chicago+style+pizza&start={index}&sa=N",
    "items": [
      {
        "title": "Pizz'a Chicago Home Page"
        // More fields for the search results
      }
      // More search results
    ]
  }
}

这是如何展示屏幕截图中的色块的例子(背景颜色对应下图中的颜色)

  • Results 11 - 20 of about 2,700,000 = startIndex
  • Results 11 - 20 of about 2,700,000 = startIndex + currentItemCount - 1
  • Results 11 - 20 of about 2,700,000 = totalItems
  • Search results = items (formatted appropriately)
  • Previous/Next = previousLink / nextLink
  • Numbered links in "Gooooooooooogle" = Derived from "pageLinkTemplate". The developer is responsible for calculating the values for {index} and substituting those values into the "pageLinkTemplate". The pageLinkTemplate's {index} variable is calculated as follows:
    • Index #1 = 0 * itemsPerPage = 0
    • Index #2 = 2 * itemsPerPage = 10
    • Index #3 = 3 * itemsPerPage = 20
    • Index #N = N * itemsPerPage

附录

附录A:JavaScript中的保留字

下列JavaScript保留字应该避免在属性名中使用

下面的清单是JavaScript中的保留字,并不能经过点访问符访问。这份清单集合了当前最新的关键字,该清单可能会根据具体的执行环境而有所变动。

来自ECMAScript 语言规范第五版

abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export exten33ds
false final finally float for function
goto
if implements import in instanceof int interface
let long
native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with
yield

除了特别说明,该页面的内容均由共同创做协议(CC BY 3.0)受权许可,示例代码均由Apache 2.0许可证受权许可)

-EOF-

 

 

Google 开源项目风格指南 (中文版) http://zh-google-styleguide.readthedocs.io/en/latest/

相关文章
相关标签/搜索