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

问题:如何在Python中检查字符串是否为有效的JSON?

在Python中,有没有办法在尝试解析字符串之前检查字符串是否为有效JSON?

例如,使用Facebook Graph API之类的东西时,有时返回JSON,有时可能返回图像文件。

In Python, is there a way to check if a string is valid JSON before trying to parse it?

For example working with things like the Facebook Graph API, sometimes it returns JSON, sometimes it could return an image file.


回答 0

您可以尝试这样做json.loads(),这将引发ValueError如果传递的字符串不能被解码为JSON。

通常,针对这种情况的“ Pythonic ”哲学被称为EAFP,因为它比许可更容易寻求宽恕

You can try to do json.loads(), which will throw a ValueError if the string you pass can’t be decoded as JSON.

In general, the “Pythonic” philosophy for this kind of situation is called EAFP, for Easier to Ask for Forgiveness than Permission.


回答 1

如果字符串是有效的json,示例Python脚本将返回一个布尔值:

import json

def is_json(myjson):
  try:
    json_object = 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

Example Python script returns a boolean if a string is valid json:

import json

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

Which prints:

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

Convert a JSON string to a Python dictionary:

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

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

Convert a python object to JSON string:

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

If you want access to low-level parsing, don’t roll your own, use an existing library: http://www.json.org/

Great tutorial on python JSON module: https://pymotw.com/2/json/

Is String JSON and show syntax errors and error messages:

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

Prints:

, 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 is capable of syntax checking, parsing, prittifying, encoding, decoding and more:

https://metacpan.org/pod/json_xs


回答 2

我要说的是,解析是您真正可以完全分辨的唯一方法。json.loads()如果格式不正确,则python 函数(几乎可以肯定)会引发异常。但是,出于示例目的,您可能只需要检查前两个非空白字符即可。

我不熟悉Facebook发送回的JSON,但是来自Web应用程序的大多数JSON字符串都将以方括号[或大{括号开头。我知道没有图像格式以这些字符开头。

相反,如果您知道可能会显示哪种图像格式,则可以检查字符串的开头以查找其签名以识别图像,如果不是图像,则假定您具有JSON。

在您要查找图形的情况下,另一个用于识别图形而不是文本字符串的简单技巧只是测试字符串的前几十个字符中的非ASCII字符(假设JSON为ASCII) )。

I would say parsing it is the only way you can really entirely tell. Exception will be raised by python’s json.loads() function (almost certainly) if not the correct format. However, the the purposes of your example you can probably just check the first couple of non-whitespace characters…

I’m not familiar with the JSON that facebook sends back, but most JSON strings from web apps will start with a open square [ or curly { bracket. No images formats I know of start with those characters.

Conversely if you know what image formats might show up, you can check the start of the string for their signatures to identify images, and assume you have JSON if it’s not an image.

Another simple hack to identify a graphic, rather than a text string, in the case you’re looking for a graphic, is just to test for non-ASCII characters in the first couple of dozen characters of the string (assuming the JSON is ASCII).


回答 3

我想出了一个通用的,有趣的解决方案:

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

I came up with an generic, interesting solution to this problem:

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

and you can use it like so:

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