当前位置: 首页 > article >正文

.Net_比对Json文件是否一致

简介

  • 该方法用于比较两个Json文件是否完全一致,仅考虑内容
  • 若两个文件中的内容只是顺序不一致,内容是一样的,那么也代表这两个文件是相等的

实现代码

  • 调用
using CompareJsonFiles;

Console.WriteLine("================= 输入信息 ===================");

Console.WriteLine("请输入源Json文件路径:");
var sourcePath = Console.ReadLine();

Console.WriteLine($"{Environment.NewLine}请输入目标Json文件路径:");
var targetPath = Console.ReadLine();

Console.WriteLine($"{Environment.NewLine}您输入的源路径为:{sourcePath},目标路径为:{targetPath}");

Console.WriteLine($"================= 输入信息 =================== {Environment.NewLine}");


CompareJsonHelper.CompareJsonFiles(sourcePath?.Trim(), targetPath?.Trim());
  • 实现
using Newtonsoft.Json.Linq;

namespace CompareJsonFiles;

/// <summary>
/// 比对Json文件的帮助类
/// </summary>
public static class CompareJsonHelper
{
    /// <summary>
    /// 比较两个JSON文件的内容
    /// </summary>
    /// <param name="sourcePath">源文件</param>
    /// <param name="targetPath">目标文件</param>
    public static void CompareJsonFiles(string? sourcePath, string? targetPath)
    {
        if (!IsExistForJsonFile(sourcePath, targetPath))
        {
            return;
        }
        
        // 加载并解析JSON文件
        var json1 = JToken.Parse(File.ReadAllText(sourcePath));
        var json2 = JToken.Parse(File.ReadAllText(targetPath));

        // 标准化JSON结构
        var normalizedSourceJson = NormalizeJson(json1);
        var normalizedTargetJson = NormalizeJson(json2);

        // 比较JSON内容
        var differences = FindDifferences(normalizedSourceJson, normalizedTargetJson, string.Empty);

        // 输出差异
        if (differences.Count == 0)
        {
            Console.WriteLine("======================== 两个文件内容一致!==============================");
        }
        else
        {
            Console.WriteLine("============================= 两个文件存在以下差异:=================================");
            foreach (var diff in differences)
            {
                Console.WriteLine(diff);
            }
        }
    }

    /// <summary>
    /// 监测源文件和目标文件是不是Json文件
    /// </summary>
    /// <param name="sourcePath"></param>
    /// <param name="targetPath"></param>
    /// <returns></returns>
    private static bool IsExistForJsonFile(string? sourcePath, string? targetPath)
    {
        if (string.IsNullOrWhiteSpace(sourcePath))
        {
            Console.WriteLine("错误信息:源文件路径不能为空");
            return false;
        }
        if (string.IsNullOrWhiteSpace(targetPath))
        {
            Console.WriteLine("错误信息:目标文件路径不能为空");
            return false;
        }
        if (!System.IO.File.Exists(sourcePath))
        {
            Console.WriteLine("错误信息:源文件不存在");
            return false;
        }
        if (!System.IO.File.Exists(targetPath))
        {
            Console.WriteLine("错误信息:目标文件不存在");
            return false;
        }
        if (Path.GetExtension(sourcePath) != ".json")
        {
            Console.WriteLine("错误信息:源文件不是Json文件");
            return false;
        }
        if (Path.GetExtension(targetPath) != ".json")
        {
            Console.WriteLine("错误信息:目标文件不是Json文件");
            return false;
        }

        return true;
    }
    
    /// <summary>
    /// 标准化JSON结构以便比较
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    private static JToken NormalizeJson(JToken token)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                var sortedObject = new JObject();
                var properties = token.Children<JProperty>().ToList();
                properties.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.Ordinal));
                foreach (var prop in properties)
                {
                    sortedObject.Add(prop.Name, NormalizeJson(prop.Value));
                }

                return sortedObject;
            case JTokenType.Array:
                var sortedArray = new JArray(token.Select(NormalizeJson).OrderBy(t => t.ToString()));
                return sortedArray;
            default:
                return token.DeepClone();
        }
    }

    /// <summary>
    /// 查找两个JSON之间的差异
    /// </summary>
    /// <param name="source"></param>
    /// <param name="target"></param>
    /// <param name="path"></param>
    /// <returns></returns>
    private static List<string> FindDifferences(JToken source, JToken target, string path)
    {
        var differences = new List<string>();

        if (source.Type != target.Type)
        {
            differences.Add($"路径 {path} 类型不同: {source.Type}{target.Type}");
            return differences;
        }

        switch (source.Type)
        {
            case JTokenType.Object:
                foreach (var property in ((JObject)source).Properties())
                {
                    if (!((JObject)target).TryGetValue(property.Name, out JToken? tryTargetValue))
                    {
                        differences.Add($"路径 {path}.{property.Name} 在第二个文件中不存在");
                        continue;
                    }

                    differences.AddRange(FindDifferences(property.Value, tryTargetValue, $"{path}.{property.Name}"));
                }

                foreach (var property in ((JObject)target).Properties())
                {
                    if (!((JObject)source).TryGetValue(property.Name, out _))
                    {
                        differences.Add($"路径 {path}.{property.Name} 在第一个文件中不存在");
                    }
                }

                break;

            case JTokenType.Array:
                var arraySource = source as JArray;
                var arrayTarget = target as JArray;

                for (var i = 0; i < Math.Max(arraySource?.Count ?? 0, arrayTarget?.Count ?? 0); i++)
                {
                    if (i >= arraySource?.Count || i >= arrayTarget?.Count)
                    {
                        differences.Add($"路径 {path}[{i}] 数组长度不一致");
                        continue;
                    }

                    differences.AddRange(FindDifferences(arraySource![i], arrayTarget![i], $"{path}[{i}]"));
                }

                break;

            default:
                if (!JToken.DeepEquals(source, target))
                {
                    differences.Add($"路径 {path} 值不同: {source}{target}");
                }

                break;
        }

        return differences;
    }
}

http://www.kler.cn/a/443888.html

相关文章:

  • Android -- 双屏异显之方法二
  • Redis篇--常见问题篇5--热Key(Hot Key,什么是热Key,服务降级,一致性哈希)
  • UIP协议栈 TCP通信客户端 服务端,UDP单播 广播通信 example
  • wxWidgets使用wxStyledTextCtrl(Scintilla编辑器)的正确姿势
  • jmeter 接口性能测试 学习笔记
  • springboot 配置Kafka 关闭自启动连接
  • RK3588, FFmpeg 拉流 RTSP, mpp 硬解码转RGB
  • IDEA中解决Edit Configurations中没有tomcat Server选项的问题
  • 如何设计一个秒杀系统
  • 功能篇:JAVA后端实现跨域配置
  • 字节面经
  • Android Studio新建项目在源码中编译
  • MySQL基础笔记(二)
  • mHandPro 动捕手套:在具身智能、VR互动及仿真教学中的卓越表现
  • 【ppt技巧】如何设置PPT带有密码的只读模式?
  • Elasticsearch 8.x 集成与 Java API 使用指南
  • 分布式链路追踪-03-分布式系统跟踪工具,如何设计 span?
  • 基于JavaWeb(SSM+MySQL)问卷调查管理系统设计与实现毕业论文
  • 不同协议下的接口测试方案设计
  • CEF127 编译指南 MacOS 篇 - 编译 CEF(六)
  • 【计算机视觉基础CV】02-入门详解图像分类、经典数据集、比赛与冠军图像模型演进史
  • OpenCV DCT图像去噪(SIMD加速)
  • linux中 umask 命令
  • 流式处理,为什么Flink比Spark Streaming好?
  • 前端JavaScript(六)---JS中的事件
  • 中软高科身份证云解码金融(银行)解决方案介绍