使用Appengine在Python中解码JSON
我有一段代码,它从一个简单的包含3个输入的表单中获取值:
//retrieves data from a form
var $form = $( this ),
prgname= $form.find('input[name="prg"]').val(),
startDate = $("#startdate").datepicker({ dateFormat: 'yy-mm-dd' }).val(),
endDate = $("#enddate").datepicker({ dateFormat: 'yy-mm-dd' }).val();
接下来这段代码会把请求发送到服务器:
var request = $.ajax({
url: "/prg/",
type: "post",
data: JSON.stringify({prg: prgname, start:startDate, end:endDate}),
contentType: 'application/json',
dataType: 'json',
success: function() {},
error: function (jqXHR, textStatus, errorThrown){};
在服务器端,我使用Python和webapp2做了以下操作,(这里是我不太确定的地方)
import json
class PrgHandler(webapp2.RequestHandler):
def post(self):
prg= cgi.escape(self.request.POST['prg'])
start_date = cgi.escape(self.request.POST['start'])
end_date = cgi.escape(self.request.POST['end'])
#some code to write to db here
....
#if successful return a success message
if success:
success_msg = [{'class': 'success', 'msg': 'Successfully saved to the database'}]
else:
success_msg = [{'class': 'error', 'msg': 'Could not saved to the database'}]
data_string = json.dumps(success_msg)
self.response.headers.add_header('content-type', 'application/json', charset='utf-8')
self.response.write(data_string)
当我收到响应时,它跳过了成功的函数,直接进入了错误处理。
记录错误值时,我没有得到任何有用的信息:
the error is:
The text status is:error
The jqXHR is:[object Object]
Chrome的控制台给我显示了这个错误:
Resource interpreted as Document but transferred with MIME type application/json:
我查了一下,StackOverflow上的解决方案都没用,我觉得这可能是服务器端代码的问题:
self.response.headers.add_header('content-type', 'application/json', charset='utf-8')
如果我把上面那行代码注释掉,Chrome就不会报错了,我只会在一个空白页面上看到正确格式的响应值:
[{"msg": "Successfully saved to the database", "class": "success"}]
在这种情况下,它确实能保存到数据库,所以我似乎找不到任何错误,除了头部信息,我也不知道该怎么继续!
编辑 看起来错误是来自服务器端,我之前把以下这行代码去掉了: event.preventDefault();
这导致了所有问题,现在至少我能清楚地知道问题出在哪里。是因为错误地获取了提交的数据,我该怎么正确处理呢?我试了以下方法:
json_data = self.request.GET.items()
decoded = json.loads(json_data)
但我在以下这行代码上遇到了TypeError错误:期待字符串或缓冲区: json_data = self.request.GET.items()
2 个回答
看看你的调试工具。你在发送请求时收到了一个JSON字符串(这是webapp2的多字典格式)。你需要用json.loads来解码这个字符串,这样就能得到一个Python对象。
下面是我用jQuery发送和接收JSON的代码:
function gaeQuery(request) {
var url = "/query";
var payload = {'jsondata' : JSON.stringify(request)};
$.post(
url,
payload,
function(response) {
procesResponse(response);
}, // succes response callback
'json', // response contains JSON content, and will be decoded in a js object
{
contentType: "application/json;charset=utf-8", // send JSON content
timeout: 20000,
tryCount: 0,
retryLimit: 3, // max 3 retries
error: function(xhr, textStatus, errorThrown) { // error handling callback
if (textStatus === 'timeout') {
this.tryCount++;
if (this.tryCount <= this.retryLimit) { //try again until retryLimit
$.ajax(this);
return;
}
alert('We have tried ' + this.retryLimit + ' times and it is still not working. We give in. Sorry.');
return;
}
if (xhr.status === 500) { // internal server error
alert('Oops! There seems to be a server problem, please try again later.');
}
else {
alert('Oops! There was a problem, sorry.'); // something went wrong
}
}
}
);
}
好的,我终于搞明白这个问题了,觉得应该把我找到的解决办法分享出来,帮助那些需要这方面信息的人,因为webapp2的文档在处理“获取”发送的json数据时并不太有用。
在客户端,我做了以下操作:
var request = $.ajax({
url: "/some/url/",
type: "POST",
data: JSON.stringify([{someval: val1, someval2:val2, someval3:val3}]),
contentType: "application/json",
dataType: 'json',
beforeSend: function() {
$('#loading-div').show();
},
complete: function(){
$('#loading-div').hide();
},
success: function(response, textStatus, jqXHR){}
});
我一开始没能立刻找到问题的原因,是因为有一行代码让我困惑,我把它和一些被注释掉的代码一起删掉了,这导致页面在提交后无法重定向。这是所有奇怪、不相关和无用的错误信息的根源:
event.preventDefault();
在服务器端,要获取发送到appengine的json数据,可以这样做:
jdata = json.loads(cgi.escape(self.request.body))
for vals in jdata:
val1 = vals['someval']
val2 = vals['someval2']
val3 = vals['someval3']
上面的内容是问题的根源,我之前没有正确处理,而在客户端没有前面那行代码,就没法找出问题所在。
总之,一旦你拿到了数据,就可以进行你需要的处理,处理完后如果需要发送一个json响应,可以添加以下几行代码:
//the data would look something like this
data = {'return_value': val1, 'return_value2': val2,
'return_value3': val3, 'return_value4': val4}
return_data = json.dumps(data)
self.response.headers.add_header('content-type', 'application/json', charset='utf-8')
self.response.write(return_data)
差点忘了,在客户端再次使用jquery访问从服务器返回的变量是非常简单的……可以这样做:
success: function(response, textStatus, jqXHR){
console.log(response.return_value);
console.log(response.return_value2);
console.log(response.return_value3);
}
希望这能帮助到正在寻找这些信息的人。