ing*_*.am 254 python parsing json
我的项目当前正在python中收到一条JSON消息,我需要从中获取一些信息.出于此目的,我们将其设置为字符串中的一些简单JSON:
jsonStr = '{"one" : "1", "two" : "2", "three" : "3"}'
Run Code Online (Sandbox Code Playgroud)
到目前为止,我一直在使用列表生成JSON请求,json.dumps但是为了做到与此相反,我认为我需要使用它,json.loads但我没有太多运气.任何人都可以给我一个片段,在上面的例子中输入"2"会返回"2"吗?
Joh*_*tta 452
非常简单:
import json
j = json.loads('{"one" : "1", "two" : "2", "three" : "3"}')
print j['two']
Run Code Online (Sandbox Code Playgroud)
jis*_*one 79
有时候你的json不是一个字符串.例如,如果您从这样的URL获取json:
j = urllib2.urlopen('http://site.com/data.json')
Run Code Online (Sandbox Code Playgroud)
你需要使用json.load,而不是json.loads:
j_obj = json.load(j)
Run Code Online (Sandbox Code Playgroud)
(很容易忘记:'s'代表'字符串')
小智 45
对于URL或FIle,请使用json.load().对于具有.json内容的字符串,请使用json.loads().
#! /usr/bin/python
import json
# from pprint import pprint
json_file = 'my_cube.json'
cube = '1'
with open(json_file) as json_data:
data = json.load(json_data)
# pprint(data)
print "Dimension: ", data['cubes'][cube]['dim']
print "Measures: ", data['cubes'][cube]['meas']
Run Code Online (Sandbox Code Playgroud)
小智 25
以下是可以帮助您的简单示例:
json_string = """
{
"pk": 1,
"fa": "cc.ee",
"fb": {
"fc": "",
"fd_id": "12345"
}
}"""
import json
data = json.loads(json_string)
if data["fa"] == "cc.ee":
data["fb"]["new_key"] = "cc.ee was present!"
print json.dumps(data)
Run Code Online (Sandbox Code Playgroud)
上面代码的输出将是:
{"pk": 1, "fb": {"new_key": "cc.ee was present!", "fd_id": "12345",
"fc": ""}, "fa": "cc.ee"}
Run Code Online (Sandbox Code Playgroud)
请注意,您可以设置dump的ident参数来打印它(例如,使用print json.dumps(data,indent = 4)时):
{
"pk": 1,
"fb": {
"new_key": "cc.ee was present!",
"fd_id": "12345",
"fc": ""
},
"fa": "cc.ee"
}
Run Code Online (Sandbox Code Playgroud)
json模块对于字符串数据,请使用json.loads:
import json\n\ntext = \'{"one" : "1", "two" : "2", "three" : "3"}\'\nparsed = json.loads(example)\nRun Code Online (Sandbox Code Playgroud)\n对于来自文件或其他类似文件的对象的数据,请使用json.load:
import io, json\n# create an in-memory file-like object for demonstration purposes.\ntext = \'{"one" : "1", "two" : "2", "three" : "3"}\'\nstream = io.StringIO(text)\nparsed = json.load(stream) # load, not loads\nRun Code Online (Sandbox Code Playgroud)\n很容易记住区别:结尾s的loads代表“字符串”。(诚然,这可能不符合标准的现代命名实践。)
请注意,json.load 不接受文件路径:
>>> json.load(\'example.txt\')\nTraceback (most recent call last):\n File "<stdin>", line 1, in <module>\n File "/usr/lib/python3.8/json/__init__.py", line 293, in load\n return loads(fp.read(),\nAttributeError: \'str\' object has no attribute \'read\'\nRun Code Online (Sandbox Code Playgroud)\n这两个函数都提供了相同的一组附加选项来自定义解析过程。从 3.6 开始,选项仅限关键字。
\n对于字符串数据,也可以使用JSONDecoder库提供的类,如下所示:
import json\ntext = \'{"one" : "1", "two" : "2", "three" : "3"}\'\ndecoder = json.JSONDecoder()\nparsed = decoder.decode(text)\nRun Code Online (Sandbox Code Playgroud)\n可以使用相同的关键字参数,但现在它们被传递给 的构造函数JSONDecoder,而不是方法.decode。该类的主要优点是它还提供了一个.raw_decode方法,该方法将忽略 JSON 结束后的额外数据:
import json\ntext_with_junk = \'{"one" : "1", "two" : "2", "three" : "3"} ignore this\'\ndecoder = json.JSONDecoder()\n# `amount` will count how many characters were parsed.\nparsed, amount = decoder.raw_decode(text_with_junk)\nRun Code Online (Sandbox Code Playgroud)\nrequests或其他隐式支持当使用流行的第三方requests库从互联网检索数据时,没有必要从对象中提取.text(或创建任何类型的类似文件的对象)Response并单独解析它。相反,该Response对象直接提供了一个.json方法来执行此解析:
import requests\nresponse = requests.get(\'https://www.example.com\')\nparsed = response.json()\nRun Code Online (Sandbox Code Playgroud)\n此方法接受与标准库功能相同的关键字参数json。
默认情况下,通过上述任何方法进行解析都会产生一个完全普通的Python 数据结构,由完全普通的内置类型 dict组成, list, str, int, float, bool(JSONtrue并false成为 Python 常量True和False) 和NoneType(JSONnull成为 Python 常量None)。
因此,处理此结果的方式与使用任何其他技术获取相同数据的方式相同。
\n因此,继续问题中的示例:
\n>>> parsed\n{\'one\': \'1\', \'two\': \'2\', \'three\': \'3\'}\n>>> parsed[\'two\']\n\'2\'\nRun Code Online (Sandbox Code Playgroud)\n我强调这一点是因为很多人似乎都期望结果有一些特别之处;那没有。它只是一个嵌套的数据结构,尽管处理嵌套有时很难理解。
\n例如,考虑像这样的解析结果result = {\'a\': [{\'b\': \'c\'}, {\'d\': \'e\'}]}。要获取\'e\'需要一次执行一个适当的步骤:a在字典中查找键给出一个列表[{\'b\': \'c\'}, {\'d\': \'e\'}];该列表的第二个元素(索引1)是{\'d\': \'e\'};\'d\'并在其中查找键给出\'e\'值。因此,相应的代码是result[\'a\'][1][\'d\']:每个索引步骤按顺序应用。
另请参阅如何从嵌套数据结构(例如从解析 JSON)中提取单个值?。
\n有时,人们想要应用更复杂的选择标准、迭代嵌套列表、过滤或转换数据等。这些是更复杂的主题,将在其他地方处理。
\n在尝试解析 JSON 数据之前,确保数据实际上是 JSON 非常重要。检查JSON 格式规范以验证预期内容。关键点:
\n该文档表示一个值(通常是一个 JSON“对象”,对应于 Python dict,但 JSON 表示的所有其他类型都是允许的)。特别是,它的每一行没有单独的条目 - 即 JSONL。
使用标准文本编码(通常为 UTF-8)后,数据是人类可读的。几乎所有文本都包含在双引号内,并在适当的情况下使用转义序列。
\n考虑一个包含以下内容的示例文件:
\n{"one": "{\\"two\\": \\"three\\", \\"backslash\\": \\"\\\\\\\\\\"}"}\nRun Code Online (Sandbox Code Playgroud)\n这里的反斜杠是JSON的转义机制。\n当使用上述方法之一进行解析时,我们得到如下结果:
\n>>> example = input()\n{"one": "{\\"two\\": \\"three\\", \\"backslash\\": \\"\\\\\\\\\\"}"}\n>>> parsed = json.loads(example)\n>>> parsed\n{\'one\': \'{"two": "three", "backslash": "\\\\\\\\"}\'}\nRun Code Online (Sandbox Code Playgroud)\n请注意,这parsed[\'one\']是 a str,而不是adict。不过,碰巧的是,该字符串本身代表“嵌入”的 JSON 数据。
要用解析结果替换嵌入数据,只需访问数据,使用相同的解析技术,然后从那里继续(例如,通过就地更新原始结果):
\n>>> parsed[\'one\'] = json.loads(parsed[\'one\'])\n>>> parsed\n{\'one\': {\'two\': \'three\', \'backslash\': \'\\\\\'}}\nRun Code Online (Sandbox Code Playgroud)\n请注意,这里的部分是包含一个\'\\\\\'字符串的表示实际反斜杠而不是两个反斜杠这遵循了通常的 Python 字符串转义规则,这让我们……
有时,人们在尝试测试涉及解析 JSON 的代码时会感到困惑,并提供不正确的输入在 Python 源代码中将当尝试测试需要使用嵌入式 JSON 的代码时,尤其会发生这种情况。
\n问题在于 JSON 格式和字符串文字格式各自具有单独的数据转义策略。Python 将处理字符串文字中的转义以创建字符串,该字符串仍然需要包含JSON 格式使用的转义序列。
\n在上面的示例中,我input在解释器提示符下使用来显示示例数据,以避免与转义混淆。下面是一个在源代码中使用字符串文字的类似示例:
>>> json.loads(\'{"one": "{\\\\"two\\\\": \\\\"three\\\\", \\\\"backslash\\\\": \\\\"\\\\\\\\\\\\\\\\\\\\"}"}\')\n{\'one\': \'{"two": "three", "backslash": "\\\\\\\\"}\'}\nRun Code Online (Sandbox Code Playgroud)\n要改用双引号字符串文字,还需要对字符串文字中的双引号进行转义。因此:
\n>>> json.loads(\'{\\"one\\": \\"{\\\\\\"two\\\\\\": \\\\\\"three\\\\\\", \\\\\\"backslash\\\\\\": \\\\\\"\\\\\\\\\\\\\\\\\\\\\\"}\\"}\')\n{\'one\': \'{"two": "three", "backslash": "\\\\\\\\"}\'}\nRun Code Online (Sandbox Code Playgroud)\n\\\\\\"输入中的每个序列都会成为\\"实际的 JSON 数据,"当由 JSON 解析器解析时,该数据就会变成(嵌入在字符串中)。类似地,\\\\\\\\\\\\\\\\\\\\\\"(五对反斜杠,然后一个转义引号)\\\\\\\\\\"在实际的 JSON 数据中变成(五个反斜杠和一个引号;等效地,两对反斜杠,然后一个转义引号),在\\\\"解析时变成(两个反斜杠和一个引号)由 JSON 解析器处理,它\\\\\\\\"在解析结果的字符串表示形式中变成(两个转义的反斜杠和一个引号)(从现在起,引号不需要转义,因为 Python 可以对字符串使用单引号;但反斜杠仍然需要转义) 。
除了选项之外strict,可用于json.load和 的关键字选项json.loads应该是回调。解析器将调用它们,传入部分数据,并使用返回的任何内容来创建总体结果。
“parse”钩子是相当不言自明的。例如,我们可以指定将浮点值转换为decimal.Decimal实例,而不是使用本机 Python float:
>>> import decimal\n>>> json.loads(\'123.4\', parse_float=decimal.Decimal)\nDecimal(\'123.4\')\nRun Code Online (Sandbox Code Playgroud)\n或者对每个值使用浮点数,即使它们可以转换为整数:
\n>>> json.loads(\'123\', parse_int=float)\n123.0\nRun Code Online (Sandbox Code Playgroud)\n或者拒绝转换 JSON 的特殊浮点值表示:
\n>>> def reject_special_floats(value):\n... raise ValueError\n... \n>>> json.loads(\'Infinity\')\ninf\n>>> json.loads(\'Infinity\', parse_constant=reject_special_floats)\nTraceback (most recent call last):\n File "<stdin>", line 1, in <module>\n File "/usr/lib/python3.8/json/__init__.py", line 370, in loads\n return cls(**kw).decode(s)\n File "/usr/lib/python3.8/json/decoder.py", line 337, in decode\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n File "/usr/lib/python3.8/json/decoder.py", line 353, in raw_decode\n obj, end = self.scan_once(s, idx)\n File "<stdin>", line 2, in reject_special_floats\nValueError\nRun Code Online (Sandbox Code Playgroud)\nobject_hook和 的定制示例object_pairs_hookobject_hook并可object_pairs_hook用于控制解析器在给定 JSON 对象时执行的操作,而不是创建 Python dict。\n提供的object_pairs_hook将使用一个参数进行调用,该参数是一组键值对列表,否则将用于dict. 它应该返回所需的dict或其他结果:
>>> def process_object_pairs(items):\n... return {k: f\'processed {v}\' for k, v in items}\n... \n>>> json.loads(\'{"one": 1, "two": 2}\', object_pairs_hook=process_object_pairs)\n{\'one\': \'processed 1\', \'two\': \'processed 2\'}\nRun Code Online (Sandbox Code Playgroud)\nobject_hook相反,将使用本来创建的 来调用提供的dict,结果将替换为:
>>> def make_items_list(obj):\n... return list(obj.items())\n... \n>>> json.loads(\'{"one": 1, "two": 2}\', object_hook=make_items_list)\n[(\'one\', 1), (\'two\', 2)]\nRun Code Online (Sandbox Code Playgroud)\n如果两者都提供,则将object_hook被忽略并且仅object_items_hook使用。
bytes/unicode混乱JSON 本质上是一种文本格式。在解析文件之前,应首先使用适当的编码将输入数据从原始字节转换为文本。
\n在 3.x 中,bytes支持从对象加载,并且将隐式使用 UTF-8 编码:
>>> json.loads(\'"text"\')\n\'text\'\n>>> json.loads(b\'"text"\')\n\'text\'\n>>> json.loads(\'"\\xff"\') # Unicode code point 255\n\'\xc3\xbf\'\n>>> json.loads(b\'"\\xff"\') # Not valid UTF-8 encoded data!\nTraceback (most recent call last):\n File "<stdin>", line 1, in <module>\n File "/usr/lib/python3.8/json/__init__.py", line 343, in loads\n s = s.decode(detect_encoding(s), \'surrogatepass\')\nUnicodeDecodeError: \'utf-8\' codec can\'t decode byte 0xff in position 1: invalid start byte\nRun Code Online (Sandbox Code Playgroud)\nUTF-8 通常被认为是 JSON 的默认格式。虽然原始规范 ECMA-404不强制要求编码(它仅描述“JSON 文本”,而不是 JSON 文件或文档),但RFC 8259要求:
\n\n\n不属于封闭生态系统的系统之间交换的 JSON 文本必须使用 UTF-8 [RFC3629] 进行编码。
\n
在这样一个“封闭的生态系统”中(即对于编码不同且不会公开共享的本地文档),首先明确应用适当的编码:
\n>>> json.loads(b\'"\\xff"\'.decode(\'iso-8859-1\'))\n\'\xc3\xbf\'\nRun Code Online (Sandbox Code Playgroud)\n同样,JSON 文件应该以文本模式打开,而不是二进制模式。如果文件使用不同的编码,只需在打开它时指定:
\nwith open(\'example.json\', encoding=\'iso-8859-1\') as f:\n print(json.load(f))\nRun Code Online (Sandbox Code Playgroud)\n在2.x中,字符串和字节序列没有正确区分,这导致了很多问题和混乱特别是在使用 JSON 时。
\n积极维护的 2.x 代码库(请注意,自 2020 年 1 月 1 日起,2.x 本身已不再维护)应始终使用unicode值来表示文本和str值来表示原始数据(str是 2.x 中的别名bytes),并接受的repr值unicode将有一个u前缀(毕竟,代码应该关心值的实际是什么,而不是它在 REPL 中的样子)。
simplejsonsimplejson 只是标准库json模块,但由外部维护和开发。它最初是在 JSON 支持添加到 Python 标准库之前创建的。在2.6中,该simplejson项目被纳入标准库,如下所示json. 当前的开发保持了对 2.5 的兼容性,尽管还有一个未维护的遗留分支应该支持早至 2.2。
标准库通常使用相当旧版本的包;例如,我的 3.8.10 安装报告
\n>>> json.__version__\n\'2.0.9\'\nRun Code Online (Sandbox Code Playgroud)\n而最新版本(截至撰写本文时)是 3.18.1。(Github 存储库中标记的版本只能追溯到 3.8.2;2.0.9 版本可以追溯到2009 年。
\n我还无法找到哪些simplejson版本对应于哪些 Python 版本的综合文档。
| 归档时间: |
|
| 查看次数: |
480290 次 |
| 最近记录: |