分享 [豆知识] RESTful JSON API 接口应该 POST 什么数据

Rei · December 11, 2011 · Last by Rei replied at February 04, 2012 · 11710 hits

http://codecampo.com/topics/388

对 HTTP 协议不熟悉的同学(比如我)容易搞混淆的地方

我觉得下面三种是等价的,只要 content type 和 post data 的格式对应起来就 OK。

application/x-www-form-urlencoded + nested http params
application/json + json data
application/xml + xml data

还有就是服务器端处理各种格式用的工具不同,json 和 xml 都有各自的 parser 和 builder

而 nested http params 一般只有框架才支持,有些框架好像不支持,或者没有一个通用的标准,或者开发者自己都不知道有这样一个东西。

不过,Rails(或者说基于 Rack 的 ruby web framwork) 对 nested http params 支持特别友好,从 form 的生成到 parser/build:

>> Rack::Utils.parse_nested_query("a[]=1&a[]=2&b[c]=3&b[d]=4")  
=> {"a"=>["1", "2"], "b"=>{"c"=>"3", "d"=>"4"}}  


>> Rack::Utils.build_nested_query(:a => ["1", "2"], :b => {:c => "3"})  
=> "a[]=1&a[]=2&b[c]=3"  

好像还有一个区别是,不同 content type 请求,返回的结果的格式也是不同的(这个我也不确定...)

#1 楼 @hooopo 试了下,Rails 可以处理 Content-Type: application/json

curl localhost:3000 -XPOST -d '{"a":1, "b":2}' -H "Content-Type: application/json"

Started POST "/" for 127.0.0.1 at 2011-12-11 17:23:01 +0800
  Processing by HomepageController#index as */*
  Parameters: {"a"=>1, "b"=>2, "homepage"=>{"a"=>1, "b"=>2, "controller"=>"homepage", "action"=>"index"}}

不知道后面的 homepage 是怎么回事。服务端处理的时候那个 as / ,应该说明了返回格式跟 Content-Type 无关(跟 Accept 以及 params 中的 format 有关)

application/x-www-form-urlencoded 是一些 Http 库的默认行为,比如 Rest-client、JQuery Ajax,用起来比较方便,不然还得教客户端编写者怎么指定 Content-Type。

application/x-www-form-urlencoded是默认行为,但是标准只支持key-value这种形式的传值。 想传递数组和哈希就得用 json 或 nested http params 这种自定义格式(非标准的,底层类库不支持)

如果是 Rails 内部使用,我推荐用 nested http params 形式,如果是 RESTful API 或富客户端应用,我倾向于使用 json

homepage 那个好像是只有 root route 的时候会这样,其他路由不会,很诡异的...

嗯,返回貌似只和 Accept 和 format 有关。

jquery 用 json 方便,因为不用 build nested params:

$.ajax({
    url: "http://localhost:3000/lists",
    dataType: "json",
    type: "POST",
    processData: false,
    contentType: "application/json",
    data: "{\"list\":{\"title\":\"test\"}}"
});

#3 楼 @hooopo 哦,原来还有这参数,那是 json 好。

附送 JSON 编码

> JSON.stringify({a:1, b:[1,2,5], c: 'test"'})
"{"a":1,"b":[1,2,5],"c":"test\""}"
You need to Sign in before reply, if you don't have an account, please Sign up first.