Python实现json串比对并输出差异结果

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Descrip    :
@Project    :tools
@File       :test.py
@Author      :guolihai
@Date        :2022/03/02 15:04
"""
import json


class JsonCompare:
    def __init__(self, second_data, first_data, debug_model=False):
        """
        :param second_data:
        :param first_data:
        :param debug_model:
        """
        self.compare_result = []  # 存放字段差异
        self.compare_error = []  # 存放字段比对异常
        self.compare(second_data, first_data)

        if debug_model:
            for i in self.compare_result:
                print('-----:{}'.format(i))
            for i in self.compare_error:
                print(i)

    def result(self):
        # s = "".join(self.compare_result)

        return self.compare_result

    def compare(self, second_data, first_data, path=''):
        try:
            if not isinstance(second_data, (list, tuple, dict)):
                # 比对非list\tuple\dict类型的数据
                if not second_data == first_data:
                    msg = {
                        # 'field': path,
                        'field': "差异位置=>" + path,
                        # 'error_type': 'field value diff',
                        'error_type': '字段的值不同',
                        'secondResp': second_data,
                        'firstResp': first_data
                    }
                    self.compare_result.append(msg)

            elif isinstance(second_data, (list, tuple)):
                # 如果新数据是list/tuple,则判断老数据是否类型一致;不一致则追加到compare_error
                if type(second_data) != type(first_data):
                    msg = {
                        # 'field': path,
                        'field': "差异位置=>" + path,
                        'error_type': "field type diff",
                        'secondResp': f"type is {type(second_data)}",
                        'firstResp': f"type is {type(first_data)}"
                    }
                    self.compare_result.append(msg)
                    return
                if len(second_data) != len(first_data):
                    msg = {
                        # 'field': path,
                        'field': "差异位置=>" + path,
                        'error_type': "field indexLength diff",
                        'secondResp': f"Length of list is {len(second_data)}",
                        'firstResp': f"Length of list is {len(first_data)}"
                    }
                    self.compare_result.append(msg)
                for index, value in enumerate(second_data):
                    try:
                        if index < len(first_data):
                            self.compare(
                                value, first_data[index], f'{path}:{index}')
                        else:
                            self.compare(value, {}, f'{path}:{index}')
                    except Exception as e:
                        self.compare_error.append(
                            f'Unknown error: {e.args}')
            else:
                # 比对值为dict类型数据
                if not isinstance(first_data, dict):
                    msg = {
                        # 'field': path,
                        'field': "差异位置=>" + path,
                        'error_type': "field type diff",
                        'secondResp': f"type is {type(second_data)}",
                        'firstResp': f"type is {type(first_data)}"
                    }
                    self.compare_result.append(msg)
                    return
                new_keys = set(second_data.keys())
                old_keys = set(first_data.keys())
                diff_keys = old_keys - new_keys  # 用于检查老数据存在某个key,但新数据不存在。
                for key, value in second_data.items():
                    try:
                        if key in first_data.keys():
                            self.compare(
                                value, first_data[key], f"{path}:{key}")
                        else:
                            msg = {
                                # 'field': f"{path}:{key}",
                                'field': "差异位置=>" + f"{path}:{key}",
                                # 'error_type': 'field missing',
                                'error_type': '字段缺少',
                                'secondResp': value,
                                # 'firstResp': f"Field of '{key}' is not exists"
                                'firstResp': f"字段 '{key}' 不存在"
                            }
                            self.compare_result.append(msg)
                    except Exception as e:
                        self.compare_error.append(
                            f'Unknown error:{e.args}')
                if diff_keys:
                    for key in diff_keys:
                        msg = {
                            # 'field': f"{path}:{key}",
                            'field': "差异位置=>" + f"{path}:{key}",
                            # 'error_type': 'field missing',
                            'error_type': '字段缺少',
                            # 'secondResp': f"Field of '{key}' is not exists",
                            'secondResp': f"字段 '{key}' 不存在",
                            'firstResp': first_data[key]
                        }
                        self.compare_result.append(msg)

        except Exception as e:
            self.compare_error.append(
                f'Unknown error:{e.args}')


if __name__ == '__main__':
    a = {"pid": "2101051131450820a0122893623", "sign": "d7c7a8c117a2a209bf096e0eeab8b21f",
         "data": {"trainDate": "2022-03-13 00:00:00", "fromStation": [{"xx": "ss"}, {"tt": ""}], "toStation": "成都"},
         "pGroupId": "2105081114363770a0175031531"}
    b = {"pid": "2101051131450820a0122893623", "timestamp": 1646189746138, "sign": "d7c7a8c117a2a209bf096e0eeab8b21f",
         "data": {"trainDate": "2022-03-13 00:00:00", "fromStation": [{"xx": "ss"}, {"tt": "55655"}], "toStation": "ff"},
         "pp": "2105081114363770a0175031531"}
    x = JsonCompare(b, a, debug_model=False).result()
    print(json.dumps(x, ensure_ascii=False))
    # print(x)
    for i in x:
        print(i)

 执行结果:

 

posted @ 2022-03-02 16:57  小路飞飞飞  阅读(490)  评论(0)    收藏  举报