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


183

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

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


3
api应该设置内容类型
John La Rooy

4
您无法指定API调用中返回的数据是什么?我不熟悉Facebook API,但这听起来很奇怪。
2011年

我已经做过一次,使用的是代码高尔夫的方式

1
大多数回复都是json,但是,如果您调用个人资料照片,它只会返回jpg
Joey Blake

Answers:


233

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

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


4
我可以看到它将如何工作。使我想到下一个问题。它将引发ValueError。我现在想做的是返回有问题的字符串,以便我可以做其他事情。到目前为止,我只得到错误消息和类型。
乔伊·布莱克

2
仅返回您loads在except子句中传递的字符串有什么问题?
John Flatness

1
没什么错,只是我这方面的菜鸟错误。看来我只是不能两次调用file.read()。但是我可以设置一个变量并使用它。那就是我所做的。
乔伊·布莱克

5
只是一个提示... json.loads('10')不会引发ValueError,我确定'10'不是有效的json ...
wahrheit 2014年

4
尽管规范指出JSON文本必须是数组或对象,但大多数编码器和解码器(包括Python的)都可以在“顶部”使用任何JSON值,包括数字和字符串。10是有效的JSON数字值。
John Flatness 2014年

144

如果字符串是有效的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


您是否认为我们应该del json_object经过验证?
阿克沙伊(Akshay)

4
为什么没有正确的验证方法?应该有一种不杀死金丝雀的错误检查方法。
Braden Best

我要说的是:仅仅因为Python允许OO并不意味着可以忽略其他部分。我应该选择A.让函数失败并使用异常(OO / Python方式),或者B.调用返回值(成功或错误)的函数,而不是引发异常,然后让我的函数出现,然后返回指示错误的标记值,以使错误在调用堆栈中冒泡,并可以根据需要使用(过程/ C方式)。就像C ++不会强迫您使用异常(可以使用errno)一样,Python也不应强迫使用它
Braden Best

@BradenBest JSON字符串验证被恶魔困扰,这使得暂停问题变得很有趣。没有数学上正确的方法来证明字符串的正确性,只能使用解析器尝试您的字符串并查看其是否正确完成。要查看为什么很难:“给我写一个程序,证明计算机程序中不存在语法错误”。那不可能 语言开发人员将对编码和解码的永恒军备竞赛充满诗意。我们最好的办法是,如果字符串对于给定引擎有效,而不是对所有可能的引擎有效,则返回yes / no。
Eric Leschinski

1
@EricLeschinski,但这里没有暂停的问题。如果解析JSON时发生错误,该程序显然会引发异常。因此,程序知道JSON输入何时无效。因此,无需使用即可具有100%的功能来检查输入是否有效try。#StopCanaryAbuse
Braden Best

2

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

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

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

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


0

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

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

1
我认为一般的解决方案是好的,但是在这种情况下,该except子句可能会隐藏任何严重的异常。捕获异常必须尽可能严格。
lucastamoios
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.