使用C#将HttpClient返回的嵌套JSON转换为指定扁平化结构
C# JSON格式转换方案
输入JSON结构
{"data": {"trafficData": {"volume": {"byHour": {"edges": [{"node": {"from": "2019-10-24T12:00:00+02:00","to": "2019-10-24T13:00:00+02:00","byDirection": [{"heading": "North","total": {"volumeNumbers": {"volume": 696}}},{"heading": "South","total": {"volumeNumbers": {"volume": 726}}}]}},{"node": {"from": "2019-10-24T13:00:00+02:00","to": "2019-10-24T14:00:00+02:00","byDirection": [{"heading": "North","total": {"volumeNumbers": {"volume": 805}}},{"heading": "South","total": {"volumeNumbers": {"volume": 751}}}]}}]}}}}}
目标JSON结构
{"data":[{"from":"2019-10-24T12:00:00+02:00","to":"2019-10-24T13:00:00+02:00","heading":"South","volume":726},{"from":"2019-10-24T13:00:00+02:00","to":"2019-10-24T14:00:00+02:00","heading":"South","volume":751}]}
现有尝试代码
// o1 is the json object input IEnumerable<JToken> jTokens = o1.Descendants().Where(p => !p.HasValues); Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) => { properties.Add(jToken.Path, jToken.ToString()); return properties; });
可行转换方案
方案一:LINQ to JSON(Newtonsoft.Json)直接处理
无需定义完整类,适合快速转换:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; // o1为已解析的JObject var edges = o1.SelectToken("data.trafficData.volume.byHour.edges") as JArray; var transformedItems = edges .SelectMany(edge => { var node = edge["node"]; var from = node["from"].ToString(); var to = node["to"].ToString(); // 筛选South方向数据 return node["byDirection"] .Where(dir => dir["heading"].Value<string>() == "South") .Select(dir => new { from = from, to = to, heading = dir["heading"].Value<string>(), volume = dir["total"]["volumeNumbers"]["volume"].Value<int>() }); }) .ToList(); var resultJson = JsonConvert.SerializeObject(new { data = transformedItems });
方案二:强类型序列化转换
先定义对应类(可通过json2csharp生成),再完成类型转换:
定义类:
// 输入结构类 public class InputRoot { public Data Data { get; set; } } public class Data { public TrafficData TrafficData { get; set; } } public class TrafficData { public Volume Volume { get; set; } } public class Volume { public ByHour ByHour { get; set; } } public class ByHour { public List<Edge> Edges { get; set; } } public class Edge { public Node Node { get; set; } } public class Node { public string From { get; set; } public string To { get; set; } public List<ByDirection> ByDirection { get; set; } } public class ByDirection { public string Heading { get; set; } public Total Total { get; set; } } public class Total { public VolumeNumbers VolumeNumbers { get; set; } } public class VolumeNumbers { public int Volume { get; set; } } // 目标结构类 public class TargetItem { public string from { get; set; } public string to { get; set; } public string heading { get; set; } public int volume { get; set; } } public class TargetRoot { public List<TargetItem> data { get; set; } }
转换代码:
using Newtonsoft.Json; // 解析输入JSON到强类型对象 var input = JsonConvert.DeserializeObject<InputRoot>(inputJson); var targetItems = input.Data.TrafficData.Volume.ByHour.Edges .SelectMany(edge => edge.Node.ByDirection .Where(dir => dir.Heading == "South") .Select(dir => new TargetItem { from = edge.Node.From, to = edge.Node.To, heading = dir.Heading, volume = dir.Total.VolumeNumbers.Volume }) ) .ToList(); var resultJson = JsonConvert.SerializeObject(new TargetRoot { data = targetItems });
两种方案均能实现需求:方案一适合临时、快速转换场景;方案二更适合需要类型安全、多次复用的业务场景。
内容的提问来源于stack exchange,提问作者user19876549
相关产品推荐
相关产品推荐

