我有一个使用Python的SimpleJSON来序列化JSON的Web服务,以及一个使用Google的可视化API的javascript /客户端。当我尝试使用Google数据表的查询方法读取JSON响应时,我收到“无效标签”错误。
我注意到Google电子表格会在对象键周围输出没有引号的JSON。我尝试在没有引号的情况下阅读JSON并且有效。我想知道使用
将SimpleJSON输出读入Google datable的最佳方法是什么 query = new google.visualization.Query("http://www.myuri.com/api/")
。
我可以使用正则表达式删除引号,但这似乎很草率。我试过的javascript JSON解析库在没有对象键的引号的情况下不会用JSON语法读取。
这里有一些很好的背景阅读:关于对象键的引用:
答案 0 :(得分:3)
您确定Google API期待JSON吗?根据我的经验,谷歌的API往往不会以你描述的方式大规模破坏 - 可能是他们实际上期望的是一种类似于JSON的不同格式。
进一步探讨了以Google期望的格式检索数据的说明:
例如,获取dataSourceUrl 从Google电子表格中,执行 以下内容:
- 在电子表格中,选择单元格范围。
- 从菜单中选择“插入”,然后选择“小工具”。
- 点击右上角的选择器打开小工具的菜单。
- 选择菜单选项“获取数据源网址”。
醇>
我这样做并在浏览器中打开了该网址。它返回的数据肯定不是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
答案 1 :(得分:1)
“无效标签”错误通常是由于JSON字符串上的盲eval()导致属性名称被误认为是标签(因为它们具有相同的语法 - “foo:”)。
eval("{ foo: 42, bar: 43 }"); // Results in invalid label
快速补救措施是确保您的JSON字符串具有括起大括号的括号:
eval("({ foo: 42, bar: 43 })"); // Works
尝试将JSON字符串括在括号中,以查看“无效标签”错误是否消失。
答案 2 :(得分:0)
事实证明:mod:json 也会在单引号中阻塞字符串。这会解决问题:
>>> from re import sub
>>> import json
>>> js = "{ a: 'a' }"
>>> json.loads(sub("'", '"', sub('\s(\w+):', r' "\1":', js)))
{u'a': u'a'}
修改(审核边缘案例)
因此提出建议的解决方案无法应对所有案例,特别是
e.g。 {foo:“一句话:就在这里!”}将改为{“foo”:“a”句子“:就在这里!”} - 杰森S 4月12日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!