¿Cómo recibir JSON en una solicitud POST en CherryPy?
(3)
¿Cómo recibir JSON de las solicitudes POST en CherryPy?
He estado en esta página , y aunque hace un buen trabajo explicando la API, sus parámetros y lo que hace; Parece que no puedo descifrar cómo usarlos para analizar el JSON entrante en un objeto.
Esto es lo que tengo hasta ahora:
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)
Y, aquí está mi llamada jquery para hacer la publicación
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
};
}
Pitón
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");
}
});
Ejemplo de trabajo:
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())
El documento al que vinculó describe un par de herramientas CherryPy que son nuevas en la versión 3.2. La herramienta json_in
básicamente hace lo anterior, con algo más de rigor, y usa la nueva API de procesamiento de cuerpo en 3.2.
Una cosa importante a tener en cuenta es que la función de post
de jQuery no parece poder enviar JSON (solo recibirlo). El argumento tipo de datos especifica el tipo de datos que espera que reciba XmlHTTPRequest, no el tipo que se enviará, y no parece haber un argumento disponible para que usted especifique el tipo que desea enviar. Usar ajax()
cambio le permite especificar eso.
La forma @cherrypy.tools.json_in()
me pareció no muy limpia ya que te obliga a utilizar cherrypy.request.json
. En cambio, el siguiente decorador intenta imitar los parámetros GET
.
Lo siguiente ayuda esto.
NOTA: Esto supone que desea devolver 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
ejemplo:
{"foo": "bar"}
get''s traducido a
@cherypy.expose
@uses_json
def endpoint(foo):
....