我如何检查字符串是否在Python中是有效的JSON ?

在Python中,在尝试解析字符串之前,是否有一种方法来检查字符串是否是有效的JSON ?

例如使用Facebook Graph API,有时它会返回JSON,有时它会返回一个图像文件。

292255 次浏览

你可以尝试执行json.loads(),如果你传递的字符串不能被解码为JSON,它将抛出ValueError

一般来说,这种情况的“神谕的”哲学被称为EAFP,表示请求原谅比请求允许容易

我想说,分析它是你真正能完全分辨的唯一方法。如果格式不正确,python的json.loads()函数(几乎肯定)将引发异常。然而,你的例子的目的是你可以只检查前两个非空格字符…

我不熟悉facebook发回的JSON,但大多数来自web应用程序的JSON字符串将以开放的正方形[或花括号{开始。据我所知,没有一种图像格式是以这些字符开头的。

相反,如果您知道可能会显示什么图像格式,则可以检查字符串开头的签名以识别图像,如果不是图像,则假定您使用了JSON。

在寻找图形的情况下,识别图形(而不是文本字符串)的另一个简单方法是在字符串的前几十个字符中测试非ASCII字符(假设JSON是ASCII)。

如果字符串是有效的,Python脚本返回一个布尔值。

import json


def is_json(myjson):
try:
json.loads(myjson)
except ValueError as e:
return False
return True

打印:

print is_json("{}")                          #prints True
print is_json("{asdf}")                      #prints False
print is_json('{ "age":100}')                #prints True
print is_json("{'age':100 }")                #prints False
print is_json("{\"age\":100 }")              #prints True
print is_json('{"age":100 }')                #prints True
print is_json('{"foo":[5,6.8],"foo":"bar"}') #prints True

将JSON字符串转换为Python字典:

import json
mydict = json.loads('{"foo":"bar"}')
print(mydict['foo'])    #prints bar


mylist = json.loads("[5,6,7]")
print(mylist)
[5, 6, 7]

将python对象转换为JSON字符串:

foo = {}
foo['gummy'] = 'bear'
print(json.dumps(foo))           #prints {"gummy": "bear"}

如果你想要访问低级解析,不要自己滚动,而是使用现有的库:http://www.json.org/

python JSON模块的优秀教程:https://pymotw.com/2/json/

是String JSON,显示语法错误和错误消息:

sudo cpan JSON::XS
echo '{"foo":[5,6.8],"foo":"bar" bar}' > myjson.json
json_xs -t none < myjson.json

打印:

, or } expected while parsing object/hash, at character offset 28 (before "bar}
at /usr/local/bin/json_xs line 183, <STDIN> line 1.

json_xs能够进行语法检查、解析、优化、编码、解码等:

https://metacpan.org/pod/json_xs

对于这个问题,我想出了一个通用的、有趣的解决方案:

class SafeInvocator(object):
def __init__(self, module):
self._module = module


def _safe(self, func):
def inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
return None


return inner


def __getattr__(self, item):
obj = getattr(self.module, item)
return self._safe(obj) if hasattr(obj, '__call__') else obj

你可以这样使用它:

safe_json = SafeInvocator(json)
text = "{'foo':'bar'}"
item = safe_json.loads(text)
if item:
# do something

在try块中非常简单。然后可以验证主体是否是有效的JSON

async def get_body(request: Request):
try:
body = await request.json()
except:
body = await request.body()
return body