【问题标题】:Google App Engine: Python: WebOb: How to get POST data in JSON format?Google App Engine:Python:WebOb:如何获取 JSON 格式的 POST 数据?
【发布时间】:2013-10-12 21:23:08
【问题描述】:

我正在 Google App Engine 平台上构建一个网络应用程序,它使用 webapp2,它使用 WebOb。我想POST 一些 JSON 格式的数据,包括嵌套数组和字典。例如:

$.post('/addvendor', {'vendor': {'name': 'test', 'description': 'a good company', 'tags':['foo', 'bar']}}, function(data){console.log(data)}, 'application/json')

但是,在服务器端,数据以平面“MultiDict”对象的形式出现,与我POSTed 的原始嵌套 JSON 对象不同。例如:

>>> print self.request.params.items()
[(u'vendor[name]', u'test'), (u'vendor[description]', u'a good company'), (u'vendor[tags][]', u'foo'), (u'vendor[tags][]', u'bar')]

这个对象很难解析。在我的服务器代码中,有没有办法在服务器上获取标准 JSON 格式的相同数据,或者至少是使用嵌套字典和数组的 Python 等效数据,以便我可以轻松地操作和检查数据?

【问题讨论】:

  • 我发现了一个类似的问题:stackoverflow.com/questions/9058233/… 不幸的是,这个问题的答案对我没有帮助,因为我无法在谷歌应用引擎环境中包含 formencode 包。我想我可以改用 Heroku 并使用 node.js。
  • $.post 是 jquery 吗?您使用的是 python 2.7.*?你能不能不做类似的事情:vendor = json.loads(self.request.get('vendor')) 你必须用import json导入json

标签: python json google-app-engine webapp2 webob


【解决方案1】:

(在 jayhendren 的帮助下更新)您应该使用 $.ajax 并手动设置 contentType='application/json; charset=utf-8' 因为 $.post 使用默认的“application/x-www-form-urlencoded;”内容类型。您还需要使用 JSON.stringify 手动将数据编码为 JSON 字符串:

$.ajax({url:'/addvendor', 
        type: 'post', 
        data:JSON.stringify({'vendor': {'name': 'test', 'description': 'a good company', 'tags':['foo', 'bar']}}), 
        contentType:'application/json; charset=utf-8',
        dataType: "json",
        success:function(data){console.log(data)}})

...

print json.loads(self.request.body)

【讨论】:

  • 我认为这个答案表明对 webob 界面缺乏了解。这是self.request.body 的值:vendor%5Bname%5D=test&vendor%5Bdescription%5D=a+good+company&vendor%5Btags%5D%5B%5D=foo&vendor%5Btags%5D%5B%5D=bar 如果我尝试将其解码为 json 对象会发生什么:ValueError: No JSON object could be decoded
  • 抱歉,忘记了一件重要的事情:jquery.ajax 的数据参数必须是纯对象或字符串 (api.jquery.com/jQuery.ajax)。如果您只传递对象,jquery 会将其转换为您所看到的查询字符串。要发送 JSON 编码的数据,您应该使用 JSON.stringify() 手动构建 JSON 字符串
  • 嗯,谢谢,这已经开始了。我仍然收到no JSON object could be decoded 错误,但至少我有一个表示 JSON 对象而不是多字典的编码字符串。这比将直接的 JSON 对象传递给 $.post 要好得多。但是,我使用了其他 API,这些 API 在 POST 将 JSON 对象发送到服务器之前不需要我 stringify。例如,在使用backbone.js 时,我可以将POSTed 上的数据解释为服务器上的JSON 对象,而无需客户端stringify 或服务器对其进行解码。
  • 终于,我明白了。在客户端:$.ajax({url:'/addvendor', type: 'post', data:JSON.stringify({'vendor': {'name': 'test', 'description': 'a good company', 'tags':['foo', 'bar']}}), success:function(data){console.log(data)}, contentType:'application/json', processData: false}) 在服务器端:json.loads(self.request.body)。这行得通,虽然我有点恼火,因为我必须JSON.stringify 对象并确保请求包含processData: false。我想我只是将ajax调用包装在客户端的一个函数中,然后调用包装器:)
  • 再次抱歉,您应该改用 $.ajax 并设置 contentType = 'application/json; charset=utf-8' 手动($.post 只是 $.ajax 的包装器,它使用默认的“application/x-www-form-urlencoded;”内容类型)。之前没有提到,因为 $.post 对我也很好,并且不会对发布数据进行 urlencodes )
【解决方案2】:

使用 json.dumps(yourdata) 不要忘记将标头 Content-Type 更改为 application/json

headers = {
"Content-Type": "application/json"
}
session.post(<url>, data=json.dumps(yourdata))

【讨论】:

  • 感谢您的回答,但我认为您没有仔细阅读问题或其他答案。我不需要从服务器发送 POST 请求,我需要使用来自客户端的 javascript AJAX 调用发送它。此外,这个问题已经解决了,从我接受的另一个答案和 cmets 的线程中可以看出。
  • @jayhendren +1 因为对于 webapp2/GAE,了解 request.body 仅在 request.content_type == 'application/json' 时才适用于 JSON 很重要。我今天在测试中进行了更改,突然间,在处理程序内部,我的 request.body 是 URL 编码的。我只需要在 POST 上添加content-type = application/json,一切就恢复正常了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多