我的Python程序接收JSON数据,我需要从中获取一些信息。我如何解析数据并使用结果呢?我认为我需要使用json.loads
来完成这项任务,但我不知道如何执行。
例如,假设我有jsonStr = '{"one" : "1", "two" : "2", "three" : "3"}'
,给定这个JSON,输入"two"
,我怎样才能得到相应的数据"2"
?
有时候,JSON文档是用来表示表格数据的,如果你有类似的东西,并试图在Pandas中使用它,请参阅Python - How to convert JSON File to Dataframe。
有些数据表面上看起来像JSON,但不是JSON。
例如,有时数据来自于将repr
应用到原生Python数据结构,结果可能使用不同的引号,使用标题大小写的True
和False
,而不是JSON强制的true
和false
,等等。
另一种常见的变体格式是将单独的有效JSON格式的数据放在输入的每一行上。(正确的JSON无法逐行解析,因为它使用了可以分隔许多行的对称括号。)这种格式称为JSONL。请参见Loading JSONL file as JSON objects。
有时来自web源的JSON数据会被填充一些额外的文本。在某些上下文中,这可以绕过浏览器中的安全限制。这被称为JSONP,在What is JSONP, and why was it created?中有描述。在其他上下文中,额外的文本实现了一种安全措施,如Why does Google prepend while(1); to their JSON responses?中所描述。无论哪种方式,在Python中处理这一点都很简单:只需识别并删除多余的文本,然后像以前一样继续。
5条答案
按热度按时间0yycz8jy1#
很简单:
pftdvrlh2#
有时你的json不是字符串,例如,如果你从一个url中获取一个json,如下所示:
你需要使用json.load,而不是json.loads:
(it很容易被遗忘:"s“代表”字符串“)
u7up0aaq3#
对于URL或文件,请使用
json.load()
。对于包含.json内容的字符串,请使用json.loads()
。kcwpcxri4#
下面是一个简单的例子,可能会对您有所帮助:
以上代码的输出为:
请注意,您可以设置dump的ident参数,以如下方式打印它(例如,当使用print json.dumps(data,indent=4)时):
fkvaft9z5#
解析数据
使用标准库
json
模块对于字符串数据,使用
json.loads
:对于来自文件或其他file-like object的数据,请使用
json.load
:两者的区别很容易记住:
loads
后面的s
代表“string”(诚然,这可能不符合现代标准的命名惯例)。注意
json.load
不接受文件路径:这两个函数都提供了相同的附加选项集来定制解析过程。从Python 3.6开始,这些选项仅限于关键字。
对于字符串数据,也可以使用库提供的
JSONDecoder
类,如下所示:同样的关键字参数也是可用的,但是现在它们被传递给
JSONDecoder
的 * 构造函数,而不是 *.decode
方法,这个类的主要优点是它还提供了一个.raw_decode
方法,这个方法将忽略JSON结尾之后的额外数据:使用
requests
或其他隐式支持当使用流行的第三方
requests
库从Internet检索数据时,没有必要从Response
对象中提取.text
(或创建任何类型的类似文件的对象)并单独解析它。相反,Response
对象直接提供了一个.json
方法来执行此解析:此方法接受与标准库
json
功能相同的关键字参数。使用结果
默认情况下,使用上述任何一种方法进行解析都会得到一个 * 非常普通 * 的Python数据结构,由 * 非常普通的内置类型 *
dict
、list
、str
、int
、float
组成。bool
(JSONtrue
和false
变为Python常量True
和False
)和NoneType
(JSONnull
变为Python常量None
)。因此,处理这个结果的工作方式 * 与 * 使用任何其他技术 * 获得 * 相同数据 * 的方式 * 相同。
因此,继续这个问题的例子:
我强调这一点是因为许多人似乎期望结果有一些特别之处;它只是一个嵌套的数据结构,处理嵌套有时候很难理解。
例如,考虑像
result = {'a': [{'b': 'c'}, {'d': 'e'}]}
这样的解析结果,要获得'e'
,需要一次执行一个适当的步骤:在Dict中查找a
密钥给出列表[{'b': 'c'}, {'d': 'e'}]
;列表第二元素(索引1
)是{'d': 'e'}
;然后在其中查找'd'
键,得到'e'
值。因此,对应的代码为result['a'][1]['d']
:按顺序应用每个索引步骤。有时候,人们希望应用更复杂的选择标准,迭代嵌套列表,过滤或转换数据,等等。这些都是将在其他地方处理的更复杂的主题。
常见的困惑来源
JSON相似
在尝试解析JSON数据之前,确保数据实际上是JSON是很重要的。检查JSON format specification以验证预期的内容。
dict
,但是JSON表示的其他类型也是允许的),特别是,它没有每行都有单独的条目--这就是JSONL。处理嵌入数据
考虑包含以下内容的示例文件:
这里的反斜线是用于JSON的转义机制,当用上面的方法解析时,我们得到如下结果:
请注意,
parsed['one']
是一个**str
,而不是**dict
,不过碰巧的是,该字符串本身表示“嵌入的”JSON数据。要用其解析结果替换嵌入的数据,只需访问数据,使用相同的解析技术,并从那里继续(例如,通过在适当的位置更新原始结果):
注意,这里的
'\\'
部分表示包含一个反斜杠的字符串,而不是两个反斜杠,这遵循了Python字符串转义的一般规则,这就引出了......JSON转义与Python字符串文字转义
有时候,当测试涉及解析JSON的代码时,人们会感到困惑,在Python源代码中提供的输入是不正确的字符串,尤其是在测试需要使用嵌入式JSON的代码时。
问题在于JSON格式和字符串字面量格式每个都有单独的转义策略,Python将处理字符串字面量中的转义以创建字符串,然后 * 仍然需要包含JSON格式 * 使用的 * 转义序列 *。
在上面的例子中,我在解释器提示符处使用
input
来显示示例数据,以避免与转义混淆,下面是一个在源代码中使用字符串文字的类似例子:要使用双引号字符串文字,字符串文字中的双引号也需要转义。
输入中的每个
\\\"
序列在实际JSON数据中变为\"
,在JSON解析器解析时变为"
(嵌入在字符串中)。类似地,\\\\\\\\\\\"
(五对反斜杠,然后是一个转义引号)变为\\\\\"
(五个反斜杠和一个引号;等价地,两对反斜杠,然后一个转义引号),当被JSON解析器解析时,它变成\\"
(两个反斜杠和一个引号),在解析结果的字符串表示中,它变成\\\\"
(两个转义反斜杠和一个引号)(从现在开始,引号不需要转义,因为Python可以对字符串使用单引号;但反斜杠仍然起作用**)。简单的定制
除了
strict
选项之外,json.load
和json.loads
的关键字选项应该是callbacks,解析器将调用它们,传入部分数据,并使用返回的任何内容来创建整个结果。“parse”钩子是非常简单明了的,例如,我们可以指定将浮点值转换为
decimal.Decimal
示例,而不是使用原生Pythonfloat
:或者对每个值都使用浮点数,即使它们可以转换为整数:
或者拒绝转换JSON对特殊浮点值的表示:
使用
object_hook
和object_pairs_hook
的自定义示例object_hook
和object_pairs_hook
可以用来控制解析器在给定JSON对象时执行的操作,而不是创建Pythondict
。提供的object_pairs_hook
将用一个参数调用,该参数是用于dict
的键-值对的列表。它应该返回所需的dict
或其他结果:提供的
object_hook
将改为使用否则将创建的dict
进行调用,并且结果将替换为:如果两者都提供,则
object_hook
将被忽略,而仅使用object_items_hook
。文本编码问题和
bytes
/unicode
混淆JSON基本上是一种文本格式。在解析文件之前,应该使用适当的编码将输入数据从原始字节转换为文本。
在Python 3.x中,支持从
bytes
对象加载,并且将隐式使用UTF-8编码:UTF-8通常被认为是JSON的默认值,虽然original specification, ECMA-404不要求编码(它只描述“JSON文本”,而不是JSON文件或文档),但RFC 8259要求:
在不属于封闭生态系统的系统之间交换的JSON文本必须使用UTF-8编码[RFC 3629]。
在这样的“封闭生态系统”中(即对于编码不同且不会公开共享的本地文档),首先明确应用适当的编码:
同样,JSON文件应该以文本模式打开,而不是二进制模式。如果文件使用不同的编码,只需在打开时指定:
在2.x中,字符串和字节序列没有被正确区分,尤其是在使用JSON时。
主动维护的2.x代码库(请注意,2.x本身has not been maintained since Jan 1, 2020)应始终使用
unicode
值表示文本,使用str
值表示原始数据(str
是bytes
在2.x中的别名),并接受unicode
值的repr
将具有u
前缀(毕竟,代码应该关心的是值实际上是什么,而不是它在REPL中的样子)。历史记录:
simplejson
simplejson
is simply the standard libraryjson
module,而不是maintained and developed externally。它最初是在JSON支持添加到Python标准库之前创建的。在Python 2.6中,simplejson
项目作为json
合并到标准库中。当前的开发维护了与Python 2.5的兼容性,尽管还有一个未维护的遗留分支应该支持最早的Python 2.2。标准库通常使用相当旧的包版本;例如,我的3.8.10安装报告
而最新的发行版(截至本文撰写之时)是3.18.1(Github库中标记的发行版最早只能追溯到3.8.2;2.0.9版本的发布日期为to 2009。
到目前为止,我还无法找到哪些
simplejson
版本对应于哪些Python发行版的全面文档。