.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; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!