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

Posted

技术标签:

【中文标题】如何在 Python 中检查字符串是不是是有效的 JSON?【英文标题】:How do I check if a string is valid JSON in Python?如何在 Python 中检查字符串是否是有效的 JSON? 【发布时间】:2011-07-27 09:10:04 【问题描述】:

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

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

【问题讨论】:

api应该设置内容类型 不能指定API调用返回什么数据?我不熟悉 Facebook API,但这听起来很奇怪。 我做过一次,但是用codegolf方式 大部分回复都是json,但是,如果你调用头像,它只会返回jpg 【参考方案1】:

您可以尝试执行json.loads(),如果您传递的字符串无法解码为JSON,则会抛出ValueError

一般而言,针对这种情况的“Pythonic”理念称为EAFP,因为请求宽恕比请求许可更容易

【讨论】:

我可以看到它是如何工作的。引导我进入下一个问题。它抛出一个 ValueError。我现在想要它做的是返回有问题的字符串,以便我可以用它做其他事情。到目前为止,我只收到了错误消息和类型。 只返回你在 except 子句中传递给 loads 的字符串有什么问题? 没什么问题,只是我的一个菜鸟错误。看来我只是不能调用 file.read() 两次。但我可以设置一个变量并使用它。这就是我所做的。 只是一个注释... json.loads('10') 不会抛出 ValueError 并且我确定 '10' 不是有效的 json ... 尽管规范规定 JSON 文本必须是数组或对象,但大多数编码器和解码器(包括 Python 的)都可以在“顶部”处理任何 JSON 值,包括数字和字符串. 10 是一个有效的 JSON 数字值。【参考方案2】:

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

是字符串 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 具有语法检查、解析、prittifying、编码、解码等功能:

https://metacpan.org/pod/json_xs

【讨论】:

您认为我们应该在验证后del json_object 吗? 为什么没有合适的验证方法?应该有一种方法可以在不杀死金丝雀的情况下进行错误检查。 我的意思是:仅仅因为 Python 允许 OO 并不意味着可以忽略其他部分。我应该选择 A. 让函数失败并使用异常(OO/Python 方式),或者 B. 调用返回值(成功或错误)而不是抛出异常的函数,然后使用我的函数,反过来,返回一个指示错误的标记值,以便错误在调用堆栈中冒泡,并且可以根据需要使用(过程/C方式)。就像 C++ 不强制你使用异常(你可以使用 errno)一样,Python 也不应该强制它 @BradenBest JSON 字符串验证被使停止问题变得有趣的恶魔所困扰。没有数学上正确的方法来证明字符串的正确性,除了用解析器尝试你的字符串并查看它是否完成时没有错误。要了解为什么很难:“给我写一个程序,证明计算机程序中不存在语法错误”。那是不可能的。语言开发人员会对编码和解码的永恒军备竞赛充满诗意。如果字符串对给定引擎有效,我们能做的最好的事情是返回是/否,而不是对所有可能的引擎。 @EricLeschinski 但这里没有停止问题。如果在解析 JSON 时发生错误,程序显然会引发异常。因此,程序知道 JSON 输入何时无效。因此,无需使用try,就可以100% 拥有一个检查输入是否有效的函数。 #StopCanaryAbuse【参考方案3】:

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

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

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

另一个识别图形而不是文本字符串的简单技巧,如果你正在寻找一个图形,只是在字符串的前几个字符中测试非 ASCII 字符(假设JSON 是 ASCII)。

【讨论】:

【参考方案4】:

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

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

【讨论】:

我认为通用解决方案很好,但在这种情况下,except 子句可能会隐藏任何严重的异常。捕获异常必须尽可能严格。【参考方案5】:

在 try 块中非常简单。然后,您可以验证正文是否是有效的 JSON

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

【讨论】:

以上是关于如何在 Python 中检查字符串是不是是有效的 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查字符串是不是是android中的有效电子邮件? [复制]

如何检查给定字符串是不是是Java中的有效JSON

如何检查给定的字符串是不是是 Windows 下的合法/有效文件名?

在过程宏中,如何检查字符串是不是是有效的变量名而不是关键字?

检查路径在 Python 中是不是有效,而不在路径的目标处创建文件

如何检查字符串是不是为有效日期