提问人:sutee 提问时间:10/7/2008 最后编辑:John Millikinsutee 更新时间:8/24/2013 访问量:3309
处理 JSON 序列化变化的正确方法
Proper way to deal with variations in JSON serialization
问:
我有一个使用 Python 的 SimpleJSON 序列化 JSON 的 Web 服务,以及一个使用 Google 的可视化 API 的 javascript/客户端。当我尝试使用 Google Data Table 的 Query 方法读取 JSON 响应时,我收到“无效标签”错误。
我注意到 Google 电子表格输出的 JSON 在对象键周围没有引号。我尝试在没有引号的情况下阅读 JSON,这很有效。我想知道使用以下命令将 SimpleJSON 输出读入 Google 数据的最佳方法是什么
query = new google.visualization.Query("http://www.myuri.com/api/")
.
我可以使用正则表达式来删除引号,但这似乎很草率。我尝试过的 javascript JSON 解析库不会在没有引号的情况下读取 JSON 语法。
这里有一些很好的背景阅读材料:围绕对象键的引号:
答:
您确定 Google API 需要 JSON 吗?根据我的经验,Google 的 API 往往不会像你所描述的那样被大规模破坏——可能是他们实际上期待一种不同的格式,只是类似于 JSON。
进一步浏览会发现以 Google 期望的格式检索数据的说明:
例如,要获取 dataSourceUrl 在 Google 电子表格中,执行 以后:
- 在电子表格中,选择单元格区域。
- 从菜单中选择“插入”,然后选择“小工具”。
- 通过单击右上角的选择器打开小工具的菜单。
- 选择菜单选项“获取数据源 URL”。
我这样做了,并在浏览器中打开了URL。它返回的数据肯定不是 JSON:
google.visualization.Query.setResponse(
{requestId:'0',status:'ok',signature:'1464883469881501252',
table:{cols: [{id:'A',label:'',type:'t',pattern:''},
{id:'B',label:'',type:'t',pattern:''}],
rows: [[{v:'a'},{v:'h'}],[{v:'b'},{v:'i'}],[{v:'c'},{v:'j'}],[{v:'d'},{v:'k'}],[{v:'e'},{v:'l'}],[{v:'f'},{v:'m'}],[{v:'g'},{v:'n'}]]}});
看起来结果旨在由浏览器直接执行。尝试修改代码以执行如下操作:
# old
return simplejson.dumps ({"requestId": 1, "status": "ok", ...})
# new
json = simplejson.dumps ({"requestId": 1, "status": "ok", ...})
return "google.visualization.Query.setResponse(%r);" % json
评论
“invalid label”错误通常是由于 JSON 字符串上的盲 eval() 导致属性名称被误认为标签(因为它们具有相同的语法 -- “foo:”)。
eval("{ foo: 42, bar: 43 }"); // Results in invalid label
快速补救措施是确保您的 JSON 字符串有括号括大括号:
eval("({ foo: 42, bar: 43 })"); // Works
尝试将 JSON 字符串括在括号中,以查看“无效标签”错误是否消失。
评论
事实证明:mod:json也会在单引号中的字符串中窒息。不过,这将解决问题:
在 python 中将 JavaScript 对象解析为 JSON:
溶液:
>>> from re import sub
>>> import json
>>> js = "{ a: 'a' }"
>>> json.loads(sub("'", '"', sub('\s(\w+):', r' "\1":', js)))
{u'a': u'a'}
编辑:(边缘案例已审查)
因此,有人提出,建议的解决方案无法应对所有情况,特别是类似
例如,{foo: “a sentence: right here!”} 将更改为 {“foo”: “a ”sentence“: right here!”}
– 杰森 S Apr 12 at 18:03
为了解决这个问题,我们只需要确保我们实际上使用的是一个键,而不仅仅是字符串中的冒号,所以我们在魔术后面做了一些观察,以暗示逗号(,)或大括号({)的存在,以确保我们正确,如下所示:
字符串中的冒号:
>>> js = "{foo: 'a sentence: right here!'}"
>>> json.loads(sub("'", '"', sub('(?<={|,)\s*(\w+):', r' "\1":', js)))
{u'foo': u'a sentence: right here!'}
这当然与执行以下操作相同:
>>> js = "{foo: 'a sentence: right here!'}"
>>> json.loads(sub('(?<={|,)\s*(\w+):', r' "\1":', js).replace("'",'"'))
{u'foo': u'a sentence: right here!'}
但后来我指出,这不是唯一的缺陷,因为引号呢:
如果我们还担心转义引号,我们将不得不更具体地说明字符串的构成。第一个引号将跟在大括号({)、空格(\s)或冒号(:)后面,而最后一个匹配的引号将出现在逗号(,)或右大括号(})之前,那么我们可以将介于两者之间的所有内容视为同一字符串的一部分,如下所示:
字符串中的附加引号:
>>> js = "{foo: 'a sentence: it\'s right here!'}"
>>> json.loads(
... sub("(?<=\s|{|:)'(.*?)'(?=,|})",
... r'"\1"',
... sub('(?<={|,)\s*(\w+):', r' "\1":', js))
... )
{u'foo': u"a sentence: it's right here!"}
关注这个领域,因为更多的边缘案例被揭示和解决。你能发现另一个吗?
或者对于更复杂的东西,一个真实世界的例子,如:npm view
从:
{ name: 'chuck', description: 'Chuck Norris joke dispenser.', 'dist-tags': { latest: '0.0.3' }, versions: '0.0.3', maintainers: 'qard ', time: { '0.0.3': '2011-08-19T22:00:54.744Z' }, author: 'Stephen Belanger ', repository: { type: 'git', url: 'git://github.com/qard/chuck.git' }, version: '0.0.3', dependencies: { 'coffee-script': '>= 1.1.1' }, keywords: [ 'chuck', 'norris', 'jokes', 'funny', 'fun' ], bin: { chuck: './bin/chuck' }, main: 'index', engines: { node: '>= 0.4.1 < 0.5.0' }, devDependencies: {}, dist: { shasum: '3af700056794400218f99b7da1170a4343f355ec', tarball: 'http://registry.npmjs.org/chuck/-/chuck-0.0.3.tgz' }, scripts: {}, directories: {}, optionalDependencies: {} }
自:
{u'author': u'Stephen Belanger ', u'bin': {u'chuck': u'./bin/chuck'}, u'dependencies': {u'coffee-script': u'>= 1.1.1'}, u'description': u'Chuck Norris joke dispenser.', u'devDependencies': {}, u'directories': {}, u'dist': {u'shasum': u'3af700056794400218f99b7da1170a4343f355ec', u'tarball': u'http://registry.npmjs.org/chuck/-/chuck-0.0.3.tgz'}, u'dist-tags': {u'latest': u'0.0.3'}, u'engines': {u'node': u'>= 0.4.1 < 0.5.0'}, u'keywords': [u'chuck', u'norris', u'jokes', u'funny', u'fun'], u'main': u'index', u'maintainers': u'qard ', u'name': u'chuck', u'optionalDependencies': {}, u'repository': {u'type': u'git', u'url': u'git://github.com/qard/chuck.git'}, u'scripts': {}, u'time': {u'0.0.3': u'2011-08-19T22:00:54.744Z'}, u'version': u'0.0.3', u'versions': u'0.0.3'}
对我有用=)
nJoy!
评论
{foo: "a sentence: right here!"}
{"foo": "a "sentence": right here!"}
评论