该风格指南是对在google创建JSON APIs而提供的指导性准则和建议,总体来说,JSON APIs符合JSON.org的规范。这份风格指南澄清和标准化了特定情况。

一、一般准则

1.注释 
    JSON对象中不应该包括注释。 
2.双引号 
    如果某个属性需要引号,则必须使用双引号。所以的属性名都必须在双引号内,字符类型的属性值必须使用双引号。其他类型值,比如 布尔或者数字,不应该使用双引号。 
3.扁平化数据 VS 结构层次 
    不能为了方便而将数据任意分组。JSOIN中的数据应该以扁平化的方式呈现,不能为了方便而将数据任意分组。但在某些情况下,比如描述单一结构的一批属性,因为它被用来保持结构层次,因而是有意义的。但是遇到这种情况还是应当慎重你考虑,记住只有语义上有意义的时候才使用它。例如,一个地址可以有两种方式,但结构化的方式对开发人员更有意义:

扁平化地址:
{
  "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"
  }
}

二、属性名规则

1.属性名格式 
    选择有意义的属性名 
属性名必须遵守以下准则:

  • 属性名应该是具有定义语义的有意义的名称
  • 属性名必须是驼峰式的 ASCII码字符串
  • 首字符必须是字母,下划线_ 或者是 符号
  • 随后的其他字符可以是字母、数字、下划线或者$
  • 应该避免使用javascript中的保留关键字
{
    "thisPropertyIsAnIdentifier": "identifier value"
    }

 

2.JSON MAP中的键名 
    在JSON MAP中键名可以使用任意的Unicode字符。 
但JSON对象作为MAP使用时,属性的名称命名规范并不使用。MAP是一个具有任意键值对的数据类型。MAP的键名不一定要遵循属性名称的命名准则,键名可以包含任意的unicode字符。客户端可以使用maps熟悉的方括号来访问这些属性

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

 

3.单数属性名 VS 复数属性名 
    数组类型应该是复数属性名,其他属性名都应该是单数。

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

 

4.命名冲突 
    通过选择新的属性名或API版本化来避免命名冲突 
新的属性可能在将来被添加进保留列表中,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"]
  }
}

三、属性值准则

1.属性值格式 
    属性值必须是unicode的布尔、数字、字符串、对象、数组或者null。

好的例子:
{
  "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 函数
}

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

{
  "volume": 10,
 
  // 即使 "balance" 属性值是零, 它也应当被保留,
  // 因为 "0" 表示 "均衡" 
  // "-1" 表示左倾斜和"+1" 表示右倾斜
  "balance": 0,
 
  // "currentlyPlaying" 是null的时候可被移除
  // "currentlyPlaying": null
}

3.枚举值 
    枚举值应该以字符串的形式出现。随着APIs的发展,枚举值可能被添加,移除或者改变。将枚举值当做字符串可以使下游用户优雅的处理枚举值的变更。

Java代码:
public enum Color {
  WHITE,
  BLACK,
  RED,
  YELLOW,
  BLUE
}

JSON对象:
{
  "color": "WHITE"
}

四、JSON结构和保留属性名

    为了使APIs保持一致的借口,JSON对象应当使用以下的结构。该结构适用于JSON的请求和响应。在这个结构中,某些属性名将被保留用作特殊用途。这些属性并不是必需的,也就是说,每个保留的属性可能出现零次或一次。但是如果服务需要这些属性,建议遵循该命名条约。下面是一份JSON结构语义表,以Orderly格式呈现(现在已经被纳入 JSONSchema)。

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?;
}*;

一些顶级保留属性名(限于篇幅,只列出少量几个): 
(1) apiVersion 
属性值类型:字符串 
父节点:- 
呈现请求中服务API期望的版本,以及在响应中保存的服务API版本。应随时提供apiVersion。这与数据的版本无关,将数据版本花应该通过其他机制来完成,比如etag。示例: 
{"apiVersion" : "2.1"} 
(2) context 
属性值类型:字符串 
父节点:- 
客户端设置这个值,服务器通过数据做出回应。这在JSON-P和批处理中很有用,用户可以使用context将响应与请求关联起来,该属性是顶级属性,因为不管响应是成功还是有错误,context总应该被呈现出来。context不同于id在cointext由用户提供而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" 部分。
  }
}

 

(3)id 
属性值类型:字符串 
父节点:- 
服务提供用于识别响应的标识(无论是请求成功还是有错误)。这对于将服务日志和单独收到的响应对应起来很有用。示例: 
{"id" : "1"} 
(4)method 
属性值类型:字符串 
父节点:- 
表示对数据即将执行或者已经被执行的动作。在JSON请求的情况下,method属性可以用来指明对数据进行何种操作。一个JSON-RPC请求的例子,其中method属性表示要在params上执行的操作:

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

(5)params 
属性值类型:对象 
父节点:- 
这个对象作为输入参数的映射发送给RPC请求。它可以和method属性一起用来执行RPC功能。若RPC方法不需要参数,则可以省略该属性。

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

(6)data 
属性值类型:对象 
父节点:- 
包含响应的所有数据。giant属性本身拥有许多保留属性名。服务可以自由的将自己的数据添加到这个对象,一个JSON响应要么应该包含一个data对象,要么应该包含一个error对象,但是不能两者都包含。如果data和error同时出现,则error对象优先。 
(7)error 
属性值类型:对象 
父节点:- 
表明错误发生,提供错误的详细信息。错误的格式支持从一个服务返回一个或多个错误。一个JSON响应可以有一个data对象或者一个error对象,但不能两者都包含。如果data和error都出现,则error优先。

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

 

五、示例

    以下为 Youtube JSON API响应对象的示例:

{
  "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
      }
    ]
  }
}

 

    分页示例

{
  "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
    ]
  }
}