如何在C#中实现两个JSON文件的RIGHT JOIN右连接操作
可行实现方案
问题根因说明
- 空引用异常是拼写错误导致:左侧JSON的分类数组键为
Categories,你代码中写的Categoris缺少字母e;右侧物品数组键为Items而非TechType,读取不存在的Token转换为JArray自然会返回空值。 Merge方法是用于合并JSON结构的工具,不支持关系型JOIN逻辑,无法实现按共同键关联匹配的需求。
实现思路
- 分别读取两个JSON文件的数组节点,增加非空校验避免异常
- 将左侧分类数据转为
CategoryID为键、CategoryDescription为值的字典,提升匹配效率 - 遍历右侧所有物品记录(符合右连接保留全部右侧记录的要求),为每条记录匹配对应分类描述,匹配不到则填空值
- 按SQL逻辑做条件过滤,输出指定字段即可
完整实现代码
using System; using System.IO; using System.Linq; using Newtonsoft.Json.Linq; namespace ConsoleApp1 { public class Program { public static void Main() { // 过滤变量 var gameVer = "2"; var cat = "metals"; // 加载两个JSON文件 JObject catObj = JObject.Load(new JsonTextReader(File.OpenText("D:/Code/Tests/categories.json"))); JObject ttObj = JObject.Load(new JsonTextReader(File.OpenText("D:/Code/Tests/techtypes.json"))); // 取出两个数组节点,非空校验避免异常 JArray categories = catObj["Categories"] as JArray ?? new JArray(); JArray items = ttObj["Items"] as JArray ?? new JArray(); // 左侧分类转字典,方便按CategoryID快速查询描述 var catDescDict = categories .ToDictionary( c => c["CategoryID"].ToString(), c => c["CategoryDescription"]?.ToString() ?? "" ); // 右连接逻辑:遍历所有右侧物品,匹配左侧分类描述 var result = items.Select(item => { string categoryId = item["CategoryID"]?.ToString() ?? ""; // 匹配不到分类则描述为空 catDescDict.TryGetValue(categoryId, out string desc); return new { CategoryDescription = desc, CategoryID = categoryId, TechName = item["TechName"]?.ToString() ?? "", SpawnID = item["SpawnID"]?.ToString() ?? "", GameVersion = item["GameVersion"]?.ToString() ?? "" }; }) // 对应SQL的WHERE条件,已修正原SQL中GameVersoion的拼写错误 .Where(i => i.GameVersion == "A" || (i.GameVersion == gameVer && i.CategoryID == cat) ) .ToList(); // 输出JSON格式结果 Console.WriteLine(JArray.FromObject(result).ToString()); } } }
输出示例
用你提供的样例JSON运行,输出结果如下:
[ { "CategoryDescription": "", "CategoryID": "crystalline", "TechName": "Quartz", "SpawnID": "quartz", "GameVersion": "A" }, { "CategoryDescription": "", "CategoryID": "metals", "TechName": "Metal Salvage", "SpawnID": "scrapmetal", "GameVersion": "A" }, { "CategoryDescription": "", "CategoryID": "outcrop", "TechName": "Limestone Outcrop", "SpawnID": "limestonechunk", "GameVersion": "A" } ]
注:样例左侧没有对应crystalline、metals、outcrop的分类数据,所以CategoryDescription为空,实际匹配到对应分类后会自动填充值
内容的提问来源于stack exchange,提问作者Vijer
相关产品推荐
相关产品推荐

