我正在从AWS(从javascript文件)中删除一些JSONP词典。在仅解析类似JSON数据的原始数据之后,在某些情况下,我获得了一个有效的JSON,并且可以在Python中成功加载它(json_data = json.loads(json_like_data)
)。但是,亚马逊的一些JSONP不包括其键周围的引号(参见下文)。
...
{type:"storageCurrentGen",sizes:
[{size:"i2.xlarge",vCPU:"4",ECU:"14",memoryGiB:"30.5",storageGB:"1 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"0.938"}}]},
{size:"i2.2xlarge",vCPU:"8",ECU:"27",memoryGiB:"61",storageGB:"2 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"1.876"}}]},
{size:"i2.4xlarge",vCPU:"16",ECU:"53",memoryGiB:"122",storageGB:"4 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"3.751"}}]},
...
对于JSONP,这仍然有效,因为它是有效的JavaScript语法。但是,Python的json.loads(json_str)
因为无效 JSON 而崩溃。
还有另一个Python模块YAML可以处理不带引号的键,但是分号后面必须有一个空格(:
)。
我认为我有两个选择。
{
| ,
)和冒号(:
)之间的字符。然后使用json.loads(...)
。:
)。然后使用yaml.load(...)
解析。我的猜测是选项2优于1.但是,我正在寻求更好的解决方案。
有没有人遇到过像这样格式不正确的JSON,并使用Python来解析它?
答案 0 :(得分:17)
您有一个HJSON document,此时您可以使用hjson
project对其进行解析:
>>> import hjson
>>> hjson.loads('{javascript_style:"Look ma, no quotes!"}')
OrderedDict([('javascript_style', 'Look ma, no quotes!')])
HJSON是JSON,不需要引用对象名称,甚至是某些字符串值,添加了注释支持和多行字符串,并且放宽了关于应该使用逗号的位置的规则(包括根本不使用逗号)。 / p>
或者您可以安装并使用demjson
library;它支持解析有效的JavaScript(缺少引号):
import demjson
result = demjson.decode(jsonp_payload)
只有当您设置strict=True
标志时,demjson
拒绝解析您的输入:
>>> import demjson
>>> demjson.decode('{javascript_style:"Look ma, no quotes!"}')
{u'javascript_style': u'Look ma, no quotes!'}
>>> demjson.decode('{javascript_style:"Look ma, no quotes!"}', strict=True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/demjson.py", line 5701, in decode
return_stats=(return_stats or write_stats) )
File "/Users/mjpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/demjson.py", line 4917, in decode
raise errors[0]
demjson.JSONDecodeError: ('JSON does not allow identifiers to be used as strings', u'javascript_style')
使用正则表达式,您可以尝试使用正则表达式来获得有效的JSON;然而,这可以导致误报。模式将是:
import re
valid_json = re.sub(r'(?<={|,)([a-zA-Z][a-zA-Z0-9]*)(?=:)', r'"\1"', jsonp_payload)
匹配{
或,
,后跟JavaScript标识符(字符,后跟更多字符或数字),后跟:
冒号。如果您的引用值包含任何此类模式,您将获得无效的JSON。
答案 1 :(得分:5)
您也可以使用简单的正则表达式执行此操作(在此特定情况下):
ll = '{type:"storageCurrentGen",sizes:\n[{size:"i2.xlarge",vCPU:"4",ECU:"14",memoryGiB:"30.5",storageGB:"1 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"0.938"}}]},\n{size:"i2.2xlarge",vCPU:"8",ECU:"27",memoryGiB:"61",storageGB:"2 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"1.876"}}]},\n{size:"i2.4xlarge",vCPU:"16",ECU:"53",memoryGiB:"122",storageGB:"4 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"3.751"}}]},'
ll_patched = re.sub('([{,:])(\w+)([},:])','\\1\"\\2\"\\3',ll)
>>> ll_patched
'{"type":"storageCurrentGen","sizes":\n[{"size":"i2.xlarge","vCPU":"4","ECU":"14","memoryGiB":"30.5","storageGB":"1 x 800 SSD","valueColumns":[{"name":"linux","prices":{"USD":"0.938"}}]},\n{"size":"i2.2xlarge","vCPU":"8","ECU":"27","memoryGiB":"61","storageGB":"2 x 800 SSD","valueColumns":[{"name":"linux","prices":{"USD":"1.876"}}]},\n{"size":"i2.4xlarge","vCPU":"16","ECU":"53","memoryGiB":"122","storageGB":"4 x 800 SSD","valueColumns":[{"name":"linux","prices":{"USD":"3.751"}}]},'