如何在 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 返回数据

PHP 后台怎么接收post请求的参数

如何在coldfusion cfc中接收JSON POST请求

如何在 Django 1.6 中使用 HTTP POST 请求接收 json 数据?

如何在 express node.js POST 请求中接收 JSON?

vue + nuxt.js - 如何读取从外部请求接收到的 POST 请求参数