2010-09-18 30 views
21

Comment recevoir JSON à partir de requêtes POST dans CherryPy?Comment recevoir JSON dans une requête POST dans CherryPy?

J'ai été à this page, et bien que ce soit un bon travail expliquant l'API, ses paramètres, et ce qu'il fait; Je n'arrive pas à comprendre comment les utiliser pour analyser le JSON entrant dans un objet.

Voici ce que j'ai jusqu'à présent:



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) 

Et, voici mon appel jquery pour faire de la poste


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

Répondre

27

Exemple de travail:

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()) 

Le doc vous lié à décrit un couple d'outils CherryPy qui sont nouveaux dans la version 3.2. L'outil json_in fait essentiellement ce qui précède, avec un peu plus de rigueur, et en utilisant la nouvelle API de traitement de corps dans 3.2.

Une chose importante à noter est que la fonction post de jQuery ne semble pas pouvoir envoyer de JSON (seulement le recevoir). L'argument dataType spécifie le type de données que vous attendez que XmlHTTPRequest reçoive , pas le type qu'il enverra, et il ne semble pas y avoir d'argument disponible pour spécifier le type que vous voulez envoyer. L'utilisation de ajax() vous permet plutôt de le spécifier.

35

Python

import cherrypy 
import simplejson 

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

     #All responses are serialized to JSON. This the same as 
     #return simplejson.dumps(result) 
     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"); 
    } 
}); 
+2

thx pour vous postez, il est à mon humble avis la manière la plus propre pour le faire. –

+0

'cherrypy.request' n'a pas d'attribut' json' – IAbstract

+2

@IAbstract vérifie que vous avez le décorateur '' '@ cherrypy.tools.json_in()' ''. –

1

J'ai trouvé la @cherrypy.tools.json_in() façon pas très propre car il vous oblige à utiliser cherrypy.request.json. Au lieu de cela, le décorateur suivant essaie d'imiter les paramètres GET.

Ce qui suit aide cela.

REMARQUE: Cela suppose que vous voulez retourner 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 

exemple:

{"foo": "bar"} 

get traduit en

@cherypy.expose 
@uses_json 
def endpoint(foo): 
     ....