如何在 CherryPy 的 POST 请求中接收 JSON?
Posted
技术标签:
【中文标题】如何在 CherryPy 的 POST 请求中接收 JSON?【英文标题】:How to receive JSON in a POST request in CherryPy? 【发布时间】:2011-04-14 05:07:10 【问题描述】:如何在 CherryPy 中接收来自 POST 请求的 JSON?
我去过this page,虽然它很好地解释了API、它的参数以及它的作用;我似乎无法弄清楚如何使用它们将传入的 JSON 解析为对象。
这是我目前所拥有的:
import cherrypy
import json
from web.models.card import card
from web.models.session import getSession
from web.controllers.error import formatEx, handle_error
class CardRequestHandler(object):
@cherrypy.expose
def update(self, **jsonText):
db = getSession()
result = "operation" : "update", "result" : "success"
try:
u = json.loads(jsonText)
c = db.query(card).filter(card.id == u.id)
c.name = u.name
c.content = u.content
rzSession.commit()
except:
result["result"] = "exception" : formatEx()
return json.dumps(result)
还有,这是我发帖的 jquery 调用
function Update(el)
el = jq(el); // makes sure that this is a jquery object
var pc = el.parent().parent();
pc = ToJSON(pc);
//$.ajaxSetup( scriptCharset : "utf-8" );
$.post( "http://localhost/wsgi/raspberry/card/update", pc,
function(data)
alert("Hello Update Response: " + data);
,
"json");
function ToJSON(h)
h = jq(h);
return
"id" : h.attr("id"),
"name" : h.get(0).innerText,
"content" : h.find(".Content").get(0).innerText
;
【问题讨论】:
【参考方案1】:Python
import cherrypy
class Root:
@cherrypy.expose
@cherrypy.tools.json_out()
@cherrypy.tools.json_in()
def my_route(self):
result = "operation": "request", "result": "success"
input_json = cherrypy.request.json
value = input_json["my_key"]
# Responses are serialized to JSON (because of the json_out decorator)
return result
javascript
//assuming that you're using jQuery
var myObject = "my_key": "my_value" ;
$.ajax(
type: "POST",
url: "my_route",
data: JSON.stringify(myObject),
contentType: 'application/json',
dataType: 'json',
error: function()
alert("error");
,
success: function()
alert("success");
);
【讨论】:
cherrypy.request
没有属性json
@IAbstract 检查您是否拥有@cherrypy.tools.json_in()
装饰器。【参考方案2】:
工作示例:
import cherrypy
import simplejson
class Root(object):
@cherrypy.expose
def update(self):
cl = cherrypy.request.headers['Content-Length']
rawbody = cherrypy.request.body.read(int(cl))
body = simplejson.loads(rawbody)
# do_something_with(body)
return "Updated %r." % (body,)
@cherrypy.expose
def index(self):
return """
<html>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type='text/javascript'>
function Update()
$.ajax(
type: 'POST',
url: "update",
contentType: "application/json",
processData: false,
data: $('#updatebox').val(),
success: function(data) alert(data);,
dataType: "text"
);
</script>
<body>
<input type='textbox' id='updatebox' value='' size='20' />
<input type='submit' value='Update' onClick='Update(); return false' />
</body>
</html>
"""
cherrypy.quickstart(Root())
您链接到的文档描述了 3.2 版中新增的几个 CherryPy 工具。 json_in
工具基本做到了以上,更严谨一些,并使用了 3.2 中新的 body processing API。
需要注意的重要一点是,jQuery 的 post
函数似乎无法发送 JSON(只能接收它)。 dataType
参数指定您希望 XmlHTTPRequest 接收的数据类型,而不是它将发送的类型,并且似乎没有可用于指定所需类型的参数发送。使用 ajax()
可以让您指定。
【讨论】:
【参考方案3】:我发现@cherrypy.tools.json_in()
的方式不是很干净,因为它迫使您使用cherrypy.request.json
。相反,以下装饰器尝试模仿 GET
参数。
以下内容对此有所帮助。
注意:这假设您要返回 JSON:
def uses_json(func):
@functools.wraps(func)
@cherrypy.tools.accept(media="application/json")
def wrapper(*args, **kwargs):
cherrypy.serving.response.headers['Content-Type'] = "application/json"
kwargs = dict(kwargs)
try:
body = cherrypy.request.body.read()
kwargs.update(json.loads(body))
except TypeError:
pass
return json.dumps(func(*args, **kwargs)).encode('utf8')
return wrapper
示例:
"foo": "bar"
得到翻译成
class Root(object):
...
@cherrypy.expose
@uses_json
def endpoint(self, foo):
....
【讨论】:
这实际上是一个非常有趣的方法。您能否解释一下为什么在响应正文中将 kwargs 与 json 合并?如果一切都来自 json,那么 kwargs 会出现什么样的参数?以上是关于如何在 CherryPy 的 POST 请求中接收 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
如何从运行尽可能快的 CherryPy BackgroundTask 返回数据
如何在coldfusion cfc中接收JSON POST请求
如何在 Django 1.6 中使用 HTTP POST 请求接收 json 数据?