【问题标题】: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

标签: python json


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 2012-04-27
      • 2018-04-07
      • 1970-01-01
      • 2022-11-28
      相关资源
      最近更新 更多