python3字典:获取json响应值来进行断言

本文详细介绍了在接口自动化测试中如何使用Python操作字典数据结构,包括获取多层级字典中的数据、遍历字典及修改字典等常见操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处:https://www.cnblogs.com/shapeL/p/9051856.html

前言:在接口自动化测试中,最后都是需要将返回结果进行断言。本文按照实际情况举例说明字典各种操作,以及如何提取响应数据来进行断言

1.dict = {'code': '200', 'message': '', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}

获取第一层字典中的数据

1 dict = {'code': '200', 'message': '', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}
2 print(dict['code'])
结果输出:
200

获取第二层字典中的数据:如果我们要获取value的值,查看发现value后的数据也是一个字典

复制代码

1 dict = {'code': '200', 'message': '', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}
2 print(dict['value'])
3 print(dict['value']['name'])
输出结果:
{'name': '嗯嗯', 'title': '36', 'value': '123'}
嗯嗯

复制代码

也可以通过dict.get()来获取键对应的值

复制代码

1 dict =  {'code': '200', 'message': '', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}
2 print(dict.get('code'))
3 print(dict.get('value').get('name'))
输出结果:
200
嗯嗯

复制代码

dict.get()和dict['key']都可以用来获取键对应值,但是存在些许区别

1 dict =  {'code': '200', 'message': '', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}
2 print(dict.get('wo'))
3 print(dict['wo'])
1 None
2 Traceback (most recent call last):
3   File "C:/Users/zy/Documents/GitHub/python3/searchTest/test.py", line 3, in <module>
4     print(dict['wo'])
5 KeyError: 'wo'

原因:dict['key']只能获取存在的值,如果不存在则触发KeyError;dict.get(key, default=None),返回指定键的值,如果值不在字典中返回默认值None

 

2.dict = {'code': '200', 'message': '', 'redirect': '', 'value': [{'supplier': 'xyz', 'title': '我们在这里'}]}

我们发现value的数据和1中的情况不同,可以获取value的值判断是什么类型的数据

1 dict = {'code': '200', 'message': '', 'redirect': '', 'value': [{'supplier': 'xyz', 'title': '我们在这里'}]}
2 print(type(dict['value']))
输出结果:
<class 'list'>

根据列表特性 索引来获取list[0]查看数据,发现列表中的每个元素是字典,又可以根据字典的特性获取到supplier的值

复制代码

1 dict = {'code': '200', 'message': '', 'redirect': '', 'value': [{'supplier': 'xyz', 'title': '我们在这里'}]}
2 print(dict['value'][0])
3 print(type(dict['value'][0]))
输出结果:
{'supplier': 'xyz', 'title': '我们在这里'}
<class 'dict'>

复制代码

1 dict = {'code': '200', 'message': '', 'redirect': '', 'value': [{'supplier': 'xyz', 'title': '我们在这里'}]}
2 print(dict['value'][0]['supplier'])
输出结果:
xyz

 

3.字典基本操作

dict = {'code': '200', 'message': '', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}

复制代码

1 # 遍历字典
2 for key in dict:
3     print(key + ':' + str(dict[key]))
4 
5 输出结果:
6 code:200
7 message:
8 redirect:
9 value:{'name': '嗯嗯', 'title': '36', 'value': '123'}

复制代码

复制代码

1 #遍历字典的键key
2 for key in dict.keys():
3     print(key)
4 
5 输出结果:
6 code
7 message
8 redirect
9 value

复制代码

复制代码

1 #遍历字典的值value
2 for value in dict.values():
3     print(value)
4 
5 输出结果:
6 200
7 
8 
9 {'name': '嗯嗯', 'title': '36', 'value': '123'}

复制代码

复制代码

1 #遍历字典的项,item()方法把字典中每对key和value组成一个元组,并把这些元组放在列表中返回
2 for item in dict.items():
3     print(item)
4 
5 输出结果:
6 ('code', '200')
7 ('message', '')
8 ('redirect', '')
9 ('value', {'name': '嗯嗯', 'title': '36', 'value': '123'})

复制代码

复制代码

 1 #修改键值
 2 dict['message'] = 'ok'
 3 print(dict)
 4 #增加新的键/值
 5 dict['wo'] = 'apple'
 6 print(dict)
 7 #输出键是'code'的条目
 8 del dict['code']
 9 print(dict)
10 #清空字典所有条目
11 dict.clear()
12 print(dict)
13 #删除字典
14 del dict
15 print(dict)
16 
17 输出结果:
18 {'code': '200', 'message': 'ok', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}}
19 {'code': '200', 'message': 'ok', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}, 'wo': 'apple'}
20 {'message': 'ok', 'redirect': '', 'value': {'name': '嗯嗯', 'title': '36', 'value': '123'}, 'wo': 'apple'}
21 {}
22 <class 'dict'>

 

<think>我们有一个任务:在Python中遍历并比较两个JSON对象的属性和值。 步骤: 1. 解析JSON字符串为Python对象(通常是字典或列表)。 2. 遍历两个对象的结构,比较对应的属性和值。 注意:JSON对象在Python中通常被解析为字典(dict)或列表(list)。因此,我们需要递归地遍历这些结构。 我们可以考虑以下情况: - 比较两个字典:比较相同的键对应的值,同时注意一个字典中可能包含另一个字典中没有的键。 - 比较两个列表:通常按顺序比较,但有时可能需要考虑无序比较(例如,集合)?但根据需求,我们可能是按顺序比较,也可能是比较集合。这里我们先按顺序比较,因为JSON数组是有序的。 但是,问题没有指定比较的规则(比如是否考虑顺序,是否允许额外属性等)。因此,我们可以先实现一个基本的比较,然后根据需求扩展。 基本思路: 1. 如果两个对象类型不同,则它们不同。 2. 如果都是基本类型(如字符串、数字、布尔值、None),则直接比较。 3. 如果是字典,则比较键的集合是否相同,然后对每个键递归比较对应的值。 4. 如果是列表,则按顺序比较每个元素(即相同索引位置的元素进行比较)。 但是,有时我们可能需要忽略顺序,那么可以将列表转换为集合(但注意:集合要求元素可哈希,且如果列表中有重复元素,集合会去重,所以不适用)。或者先排序再比较(但要求元素可排序)。 由于问题没有明确,我们先实现一个按顺序比较的版本,然后可以扩展为忽略顺序的比较(但需要明确规则)。 另外,我们还需要考虑嵌套的情况。 我们可以写一个递归函数来比较两个对象。 但是,注意:直接递归在深度很大时可能栈溢出,但对于一般的JSON数据,深度通常不会太大。 另外,我们还需要考虑如何输出差异(比如哪些地方不同)。我们可以返回一个布尔值,或者返回一个差异报告。 根据问题,我们可能需要遍历并比较,所以我们可以设计一个函数来递归遍历并记录差异。 这里我们设计一个函数:deep_compare(obj1, obj2, path=&#39;&#39;),返回一个差异列表(如果相同则返回空列表)。 差异列表的每个元素可以是一个字符串,描述差异的位置和原因。 例如: - 类型不同:在路径/path处,类型不同:type1 vs type2。 - 值不同:在路径/path处,值不同:value1 vs value2。 - 键缺失:在路径/path处,obj1有键key1而obj2没有;或者obj2有键key1而obj1没有。 - 列表长度不同:在路径/path处,列表长度不同:len1 vs len2。 但是,问题只要求遍历并比较,我们可以根据需求选择输出差异信息。 由于问题没有明确输出格式,我们假设需要找出所有差异。 步骤: 1. 将JSON字符串解析为Python对象(如果输入是字符串的话)。 2. 调用比较函数。 示例代码: 注意:我们假设输入已经是Python对象(字典或列表),或者我们可以先解析。 下面我们编写一个函数,它可以比较两个Python对象(由JSON解析得到)并返回差异列表。 我们先不考虑循环引用,因为JSON数据通常是无环的。 实现: 定义差异类型: - 类型不同 (TYPE_MISMATCH) - 值不同 (VALUE_MISMATCH) - 键缺失 (KEY_MISSING) - 列表长度不同 (LENGTH_MISMATCH) 我们用一个元组或字典来表示一个差异,但为了简单,我们用字符串描述,并收集到一个列表中。 函数签名: def deep_compare(obj1, obj2, path=&#39;&#39;): # 返回一个差异列表 具体实现: 1. 首先比较类型: if type(obj1) != type(obj2): return [f"在路径 {path} 处: 类型不同, {type(obj1)} 与 {type(obj2)}"] 2. 根据类型处理: - 如果是基本类型(None, bool, int, float, str): 直接比较值 - 如果是字典:比较键集合 all_keys = set(obj1.keys()) | set(obj2.keys()) 遍历每个键,如果键在obj1中不在obj2中,则记录obj2缺失该键;反之亦然;如果都存在,则递归比较该键对应的值。 - 如果是列表(或元组,但JSON只有列表): 先比较长度,如果长度不同,直接记录差异。 然后遍历索引,对每个索引位置递归比较。 3. 注意:对于其他类型(如集合),JSON不支持,所以我们不考虑。 但是,JSON中只有null, boolean, number, string, array, object(对应Python的None, bool, int/float, str, list, dict)。 因此,我们只需要处理这些类型。 代码实现: 注意:浮点数比较可能涉及精度问题,但这里我们先忽略,使用==比较。如果需要,可以自定义比较函数。 下面我们写一个函数,它返回差异列表。 示例: 假设有两个JSON对象(已经解析为Python对象): a = {"name": "Alice", "age": 30} b = {"name": "Bob", "age": 30} 比较后,应该返回:在路径 /name 处: 值不同, &#39;Alice&#39; 与 &#39;Bob&#39; 注意:路径表示法,我们可以用点号或者斜杠,这里我们用点号(但字典键中可能有点,所以用方括号表示?)。为了简单,我们用点号连接,但遇到字典键时,我们使用类似JavaScript的方式:用点号连接,但如果键包含特殊字符,则用方括号。但为了简化,我们直接使用字符串表示路径,对于字典键,我们使用`.key`,对于列表索引,使用`[index]`。 例如: path = &#39;&#39; 表示根 然后进入字典的键&#39;name&#39;,则path变为&#39;.name&#39; 进入列表索引0,则path变为&#39;[0]&#39; 但是,根路径我们表示为&#39;&#39;,然后第一个键前面会多一个点,我们可以处理一下:如果path为空,则新路径就是键名,否则为path+&#39;.&#39;+键名。列表索引则直接加`[i]`。 具体: - 对于字典:当前路径为path,处理键key时,新路径 = path + (&#39;.&#39; if path else &#39;&#39;) + key - 对于列表:新路径 = path + f&#39;[{i}]&#39; 但是,根路径下直接是列表,那么第一个元素就是[0],所以不用点。 我们这样构建路径: 在根路径下,如果遇到字典键key,则新路径为`key`(如果path为空)或`path.key`(如果path不为空)。 但是,为了避免根路径下出现空字符串加点的情形,我们可以这样: if path == &#39;&#39;: new_path = str(key) # 对于字典键 else: new_path = path + &#39;.&#39; + str(key) 但是,对于列表索引,我们使用: new_path = path + &#39;[&#39; + str(i) + &#39;]&#39; 但是,这样会导致字典键和列表索引的表示方式不同,但这是合理的。 但是,注意:字典键可能是整数?虽然JSON中键必须是字符串,但Python字典键可以是整数(如果JSON字符串是数字,解析后键也是字符串)。因为JSON标准规定键必须是字符串。所以我们可以将键都当作字符串处理。 所以,我们假设字典键都是字符串(或数字字符串,但解析后都是字符串)。 但是,在Python中解析JSON,键总是字符串。 因此,我们可以安全地使用字符串形式。 实现代码: 注意:递归深度,如果数据量很大,可能会栈溢出。但对于一般数据,可以接受。 我们开始写代码: 首先,我们定义处理基本类型的函数,然后处理字典和列表。 由于我们只需要比较,我们这样写: 伪代码: diffs = [] 类型不同: diffs.append(类型不同的信息) return diffs # 因为类型不同,不需要继续比较 如果是基本类型(None, bool, int, float, str): if obj1 != obj2: diffs.append(值不同的信息) return diffs 如果是字典: keys1 = set(obj1.keys()) keys2 = set(obj2.keys()) # 检查缺失的键 for key in keys1 - keys2: new_path = ... diffs.append(f"在路径 {new_path} 处: 第二个对象中缺失键 &#39;{key}&#39;") for key in keys2 - keys1: new_path = ... diffs.append(f"在路径 {new_path} 处: 第一个对象中缺失键 &#39;{key}&#39;") # 共同键 for key in keys1 & keys2: new_path = ... # 递归比较 sub_diffs = deep_compare(obj1[key], obj2[key], new_path) diffs.extend(sub_diffs) return diffs 如果是列表: if len(obj1) != len(obj2): diffs.append(f"在路径 {path} 处: 列表长度不同, {len(obj1)} 与 {len(obj2)}") # 注意:这里我们可以选择比较共同长度部分,也可以直接返回。我们选择比较共同长度部分。 min_len = min(len(obj1), len(obj2)) else: min_len = len(obj1) for i in range(min_len): new_path = path + f&#39;[{i}]&#39; sub_diffs = deep_compare(obj1[i], obj2[i], new_path) diffs.extend(sub_diffs) # 如果有一个列表更长,那么超出部分都是缺失的?但我们已经在上面报告了长度不同,所以这里不需要再报告每个元素缺失。 return diffs 其他类型(我们不考虑,但JSON没有其他类型,所以可以忽略) 注意:我们假设输入是JSON兼容的类型。 但是,如果传入的是其他类型(比如自定义对象),则可能出错。所以这个函数只适用于JSON解析后的对象。 现在,我们写一个函数来封装,如果输入是JSON字符串,则先解析。 我们可以这样: def compare_json(json_str1, json_str2): import json obj1 = json.loads(json_str1) obj2 = json.loads(json2) return deep_compare(obj1, obj2) 或者,如果已经是对象,可以直接调用deep_compare。 下面我们实现deep_compare函数。 注意:浮点数比较的精度问题,但这里我们先不处理,因为问题没有要求。 另外,我们可能希望忽略某些键,或者自定义比较规则,但这里我们先实现基本功能。 代码实现: 我们使用上面描述的路径构建方法。 注意:为了避免在根路径下出现多余的符号,我们这样构建路径: 对于字典键: if path == &#39;&#39;: new_path = key else: new_path = path + &#39;.&#39; + key 对于列表索引: new_path = path + &#39;[&#39; + str(i) + &#39;]&#39; 但是,根路径下是列表,那么第一个元素路径就是&#39;[0]&#39;,这是可以的。 示例:根路径下有一个列表,然后列表的第一个元素是一个字典,该字典有一个键&#39;name&#39;,那么路径就是&#39;[0].name&#39; 下面我们写代码:</think>### 在Python中遍历并比较JSON对象的属性和值 在Python中处理JSON对象时,通常需要遍历其结构并比较属性值。以下是完整的实现方法: #### 1. **解析JSON对象** 首先将JSON字符串解析为Python字典(或列表): ```python import json json_str1 = &#39;{"name": "Alice", "age": 30, "pets": ["Dog", "Cat"]}&#39; json_str2 = &#39;{"name": "Bob", "age": 30, "pets": ["Cat", "Rabbit"]}&#39; obj1 = json.loads(json_str1) # 解析为字典 obj2 = json.loads(json_str2) ``` #### 2. **递归遍历比较函数** 使用深度优先搜索(DFS)递归比较嵌套结构: ```python def compare_json(obj1, obj2, path="", differences=None): if differences is None: differences = [] # 类型不同直接返回差异 if type(obj1) != type(obj2): differences.append(f"路径 {path}: 类型不同 ({type(obj1)} vs {type(obj2)})") return differences # 基本类型直接比较值 if isinstance(obj1, (int, float, str, bool, type(None))): if obj1 != obj2: differences.append(f"路径 {path}: 值不同 ({obj1} vs {obj2})") return differences # 比较字典的键值对 if isinstance(obj1, dict): all_keys = set(obj1.keys()) | set(obj2.keys()) for key in all_keys: new_path = f"{path}.{key}" if path else key if key not in obj1: differences.append(f"路径 {new_path}: 第一个对象缺失键") elif key not in obj2: differences.append(f"路径 {new_path}: 第二个对象缺失键") else: compare_json(obj1[key], obj2[key], new_path, differences) # 比较列表元素 elif isinstance(obj1, list): if len(obj1) != len(obj2): differences.append(f"路径 {path}: 列表长度不同 ({len(obj1)} vs {len(obj2)})") for i, (item1, item2) in enumerate(zip(obj1, obj2)): compare_json(item1, item2, f"{path}[{i}]", differences) return differences ``` #### 3. **执行比较并输出结果** ```python diffs = compare_json(obj1, obj2) if not diffs: print("两个JSON对象完全相同") else: print("发现差异:") for diff in diffs: print(f" - {diff}") ``` #### 4. **示例输出** 对于上述`json_str1`和`json_str2`,输出结果: ``` 发现差异: - 路径 name: 值不同 (Alice vs Bob) - 路径 pets[0]: 值不同 (Dog vs Cat) - 路径 pets[1]: 值不同 (Cat vs Rabbit) ``` #### 关键点说明 1. **路径跟踪**:使用`path`参数记录当前属性的访问路径(如`.age`或`pets[0]`) 2. **类型处理**: - 基本类型(数字/字符串等)直接比较值 - 字典比较键的存在性和嵌套值 - 列表按顺序比较元素(需注意顺序敏感性) 3. **差异收集**:通过列表递归收集所有差异点 4. **复杂结构**:支持任意层级的嵌套对象(字典/列表混合) > **注意**:对于无序列表比较,需先排序(如`sorted(obj1.items())`),但会丢失原顺序信息[^1]。若需忽略顺序,可改用集合比较(但要求元素可哈希且唯一)。 #### 应用场景 - API响应验证 - 配置文件差异检测 - 数据迁移校验 - 单元测试中的JSON断言
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值