深入解析Python中的JSON比较

 更新时间:2023年09月18日 09:28:49   作者:郝同学的测开笔记  
进行接口自动化时,有时候我们需要断言的数据比较多,一个字段一个字段进行断言比较麻烦,那么如何利用Python实现轻松判断数据格式是否相同呢,下面小编就为大家详细讲讲

前言

进行接口自动化时,有时候我们需要断言的数据比较多,一个字段一个字段进行断言比较麻烦,如果可以直接断言整个响应结果,岂不美哉,那该如何实现该功能呢?

递归

在进入正式实现前,我们先简单说一下递归。因为该功能我们主要使用递归实现,以防小伙伴们看不懂。

是什么?

递归是一种算法或函数设计方法,它通过将一个问题不断分解成规模更小的子问题来解决原始问题。在 Python 中,递归是一种函数自身调用自身的过程。通过递归,程序可以在问题空间中向下深入,并通过返回值将解决子问题的结果合并起来,最终获得整个问题的解。

如何用?

在 Python 中使用递归,首先需要定义边界条件,即递归的结束条件。当满足边界条件时,递归停止,返回结果。同时,还需要定义递归情况,即在未满足边界条件时,如何继续递归调用函数来解决子问题。递归函数应该能够将问题领域缩小,使其逐渐接近边界条件。

隐藏风险

首先,递归可能会导致堆栈溢出,特别是在处理大规模问题时。其次,递归的执行效率可能较低,因为每次递归都需要保存函数调用的上下文。此外,递归需要合理设置边界条件,否则可能导致无限循环和程序崩溃。

在编写递归函数时,需要仔细考虑边界条件和递归情况,确保递归能够正确结束,并得到期望的结果。同时,为了提高递归性能,可以考虑使用尾递归优化或迭代等技术。

案例实现

有了递归的基本了解,接下来进入正题,我们将实现如何断言整个接口响应数据。

class AssertInfo:
    data = []
​
​
def diff_json(response_data, assert_data):
    if isinstance(response_data, dict):
        for key in assert_data:
            if key not in response_data:
                info = f"Response data has no key: {key}"
                print(info)
                AssertInfo.data.append(info)
        for key in response_data:
            if key in assert_data:
                diff_json(response_data[key], assert_data[key])
            else:
                info = f"Assert data has not key: {key}"
                print(info)
    elif isinstance(response_data, list):
        if len(response_data) == 0:
            print("response is []")
        if len(response_data) != len(assert_data):
            print(f"list len: '{len(response_data)}' != '{len(assert_data)}'")
​
        if response_data:
            if isinstance(response_data[0], dict):
                response_data = sorted(response_data, key=lambda x: x[list(response_data[0].keys())[0]])
            else:
                response_data = sorted(response_data)
        if assert_data:
            if isinstance(assert_data[0], dict):
                assert_data = sorted(assert_data, key=lambda x: x[list(assert_data[0].keys())[0]])
            else:
                assert_data = sorted(assert_data)
​
        for src_list, dst_list in zip(response_data, assert_data):
            diff_json(src_list, dst_list)
    else:
        if str(response_data) != str(assert_data):
            info = f"Value are not equal: {response_data}"
            print(info)
            AssertInfo.data.append(info)

代码其实也不难理解,我们做一个简单解释:

这是一个用于比较两个 JSON 数据格式是否相同的函数。每个部分的功能:

1.函数名称:diff_json(response_data, assert_data)

参数:response_data 是接口响应数据,assert_data 是期望的断言数据。

2.if isinstance(response_data, dict):

如果 response_data 是字典类型,则进入该条件判断。

循环遍历 assert_data 中的每个键(key):

如果键(key)不在 response_data 中,则打印信息表示响应数据缺少该键(key)。

循环遍历 response_data 中的每个键(key):

  • 如果键(key)在 assert_data 中,则递归调用 diff_json 函数进行比较。
  • 否则,打印信息表示断言数据缺少该键(key)。

3.elif isinstance(response_data, list):

如果 response_data 是列表类型,则进入该条件判断。

检查响应数据和断言数据的长度是否相等,如果不相等,则打印信息表示长度不一致。

如果 response_data 不为空:

  • 如果列表中的元素是字典类型,按照字典键(key)的值进行排序。
  • 如果列表中的元素不是字典类型,进行普通的排序。

如果 assert_data 不为空:

  • 如果列表中的元素是字典类型,按照字典键(key)的值进行排序。
  • 如果列表中的元素不是字典类型,进行普通的排序。

使用 zip 函数同时迭代 response_dataassert_data

对于每个对应位置的元素,递归调用 diff_json 函数进行比较。

4.else:

  • 如果response_data 既不是字典类型也不是列表类型,则进入该条件判断。
  • 如果 response_dataassert_data 的值不相等,则打印信息表示值不相等。

这个函数通过递归的方式,遍历并比较两个 JSON 数据结构的每一个键(key)和值。如果存在差异,将会打印出对应的信息。在需要断言和验证接口返回数据时,可以使用该函数进行检查。

好了,那我们看一看测试效果:

response_data = {
    "name": "Alice",
    "age": 25,
    "email": "alice@example.com"
}
​
assert_data = {
    "name": "Alice",
    "email": "Alice@example.com"
}
​
diff_json(response_data, assert_data)

执行之后,会打印出如下结果:

Assert data has not key: age
Value are not equal: alice@example.com

完美解决!

最后

这个功能还是很实用的,大部分接口响应内容都比较复杂,想要断言的内容比较多时就比较麻烦,而这个函数可以比较两个 JSON 数据格式是否相同,节省了很多时间,提高编写接口用例的效率。

到此这篇关于深入解析Python中的JSON比较的文章就介绍到这了,更多相关Python JSON内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python中实现栈的三种方法

    python中实现栈的三种方法

    这篇文章主要介绍了python中实现栈的三种方法,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2020-12-12
  • 利用python绘制笛卡尔直角坐标系

    利用python绘制笛卡尔直角坐标系

    这篇文章主要介绍了利用python绘制笛卡尔直角坐标系,python绘图主要用到matplotlib绘图模块,利用matplotlib模块画出上面的正弦函,需要的朋友可以参考一下
    2022-03-03
  • Python中os模块的简单使用及重命名操作

    Python中os模块的简单使用及重命名操作

    这篇文章主要给大家介绍了关于Python中os模块的简单使用及重命名操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Python jieba库文本处理词性标注和关键词提取进行文本情感分析

    Python jieba库文本处理词性标注和关键词提取进行文本情感分析

    这篇文章主要为大家介绍了Python使用中文文本处理利器jieba库中的词性标注和关键词提取功能进行文本情感分析实例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 20行Python代码实现一款永久免费PDF编辑工具

    20行Python代码实现一款永久免费PDF编辑工具

    本文主要介绍了Python代码实现一款永久免费PDF编辑工具,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 利用python3随机生成中文字符的实现方法

    利用python3随机生成中文字符的实现方法

    最近在学习python3,发现网上关于ptyhon3随机生成中文的资料非常少,所以决定将自己实现的方法分享下,下面这篇文章主要给大家介绍了关于利用python3随机生成中文字符的实现方法,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-11-11
  • Python线性网络实现分类糖尿病病例

    Python线性网络实现分类糖尿病病例

    什么是线性规划?想象一下,您有一个线性方程组和不等式系统。这样的系统通常有许多可能的解决方案。线性规划是一组数学和计算工具,可让您找到该系统的特定解,该解对应于某些其他线性函数的最大值或最小值
    2022-10-10
  • Python实现简单的俄罗斯方块游戏

    Python实现简单的俄罗斯方块游戏

    这篇文章主要为大家详细介绍了Python实现简单的俄罗斯方块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 浅谈sklearn中predict与predict_proba区别

    浅谈sklearn中predict与predict_proba区别

    这篇文章主要介绍了浅谈sklearn中predict与predict_proba区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06
  • Qt6中重大改变的QtMultimedia多媒体模块实现

    Qt6中重大改变的QtMultimedia多媒体模块实现

    本文主要介绍了Qt6中重大改变的QtMultimedia多媒体模块实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09

最新评论