【问题标题】:How to receive JSON in a POST request in CherryPy?如何在 CherryPy 的 POST 请求中接收 JSON?
【发布时间】: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
    };
}

【问题讨论】:

    标签: json post cherrypy


    【解决方案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 会出现什么样的参数?
      猜你喜欢
      • 1970-01-01
      • 2018-10-04
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 2015-07-13
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多