C#中JSON转XML:实现每个对象对应单行XML结构并过滤字段
解决C#中JSON转指定格式XML的问题
没问题!我来帮你搞定这个JSON转XML的需求——你要的是只提取特定字段,把每个船舶数据转成带属性的<row>元素,最后用<vessel>包裹起来对吧?下面我给你两种常用的实现方案,都是直接生成你想要的结构:
方案一:用自定义类+Json.NET(类型安全)
这种方式适合长期维护的代码,类型安全不容易出错。首先我们只定义需要用到的类,忽略不需要的paging、timestamp等字段:
// 只定义需要解析的字段,其他字段会被自动忽略 public class VesselData { public List<Vessel> Data { get; set; } } public class Vessel { public long Mmsi { get; set; } public long Imo { get; set; } public LastKnownPosition Last_Known_Position { get; set; } } public class LastKnownPosition { public Geometry Geometry { get; set; } } public class Geometry { public List<double> Coordinates { get; set; } }
然后编写转换逻辑,用Json.NET解析JSON,再用XDocument构建XML:
using Newtonsoft.Json; using System.Xml.Linq; // 你的原始JSON字符串 string json = @"{""paging"": {""limit"": 100, ""total"": 1394, ""next"": ""Mg=="", ""previous"": null}, ""data"": [ {""mmsi"": 538006090, ""imo"": 9700665, ""last_known_position"": {""timestamp"": ""2017-12-18T20:24:27+00:00"", ""geometry"": {""type"": ""Point"", ""coordinates"": [60.87363, -13.02203]}}}, {""mmsi"": 527555481, ""imo"": 970000, ""last_known_position"": {""timestamp"": ""2017-12-18T20:24:27+00:00"", ""geometry"": {""type"": ""Point"", ""coordinates"": [4.57883, 3.76899]}}}]}}"; // 反序列化JSON到自定义对象 var vesselData = JsonConvert.DeserializeObject<VesselData>(json); // 构建XML结构 var rootElement = new XElement("vessel"); foreach (var vessel in vesselData.Data) { // 提取坐标:注意JSON里coordinates的顺序是[纬度, 经度],对应你期望的lat和lon var rowElement = new XElement("row", new XAttribute("mmsi", vessel.Mmsi), new XAttribute("imo", vessel.Imo), new XAttribute("lat", vessel.Last_Known_Position.Geometry.Coordinates[0]), new XAttribute("lon", vessel.Last_Known_Position.Geometry.Coordinates[1]) ); rootElement.Add(rowElement); } // 生成XML字符串:如果要紧凑格式(所有内容一行)用SaveOptions.None,要格式化换行用默认ToString() string xmlOutput = rootElement.ToString(); Console.WriteLine(xmlOutput);
方案二:用JObject动态解析(无需定义类)
如果只是临时处理,不想写一堆类,可以用JObject直接解析JSON节点,更灵活:
using Newtonsoft.Json.Linq; using System.Xml.Linq; string json = @"{""paging"": {""limit"": 100, ""total"": 1394, ""next"": ""Mg=="", ""previous"": null}, ""data"": [ {""mmsi"": 538006090, ""imo"": 9700665, ""last_known_position"": {""timestamp"": ""2017-12-18T20:24:27+00:00"", ""geometry"": {""type"": ""Point"", ""coordinates"": [60.87363, -13.02203]}}}, {""mmsi"": 527555481, ""imo"": 970000, ""last_known_position"": {""timestamp"": ""2017-12-18T20:24:27+00:00"", ""geometry"": {""type"": ""Point"", ""coordinates"": [4.57883, 3.76899]}}}]}}"; // 解析JSON为动态对象 JObject jsonObj = JObject.Parse(json); JArray dataArray = jsonObj["data"] as JArray; var rootElement = new XElement("vessel"); foreach (JObject item in dataArray) { // 直接提取需要的字段 long mmsi = (long)item["mmsi"]; long imo = (long)item["imo"]; double lat = (double)item["last_known_position"]["geometry"]["coordinates"][0]; double lon = (double)item["last_known_position"]["geometry"]["coordinates"][1]; rootElement.Add(new XElement("row", new XAttribute("mmsi", mmsi), new XAttribute("imo", imo), new XAttribute("lat", lat), new XAttribute("lon", lon) )); } string xmlOutput = rootElement.ToString(); Console.WriteLine(xmlOutput);
如果你用System.Text.Json(.NET Core/.NET 5+)
如果项目用的是微软原生的System.Text.Json,只需要调整反序列化的部分,类上要加JsonPropertyName特性匹配JSON的蛇形命名:
using System.Text.Json; using System.Text.Json.Serialization; using System.Xml.Linq; public class VesselData { [JsonPropertyName("data")] public List<Vessel> Data { get; set; } } public class Vessel { [JsonPropertyName("mmsi")] public long Mmsi { get; set; } [JsonPropertyName("imo")] public long Imo { get; set; } [JsonPropertyName("last_known_position")] public LastKnownPosition LastKnownPosition { get; set; } } public class LastKnownPosition { [JsonPropertyName("geometry")] public Geometry Geometry { get; set; } } public class Geometry { [JsonPropertyName("coordinates")] public List<double> Coordinates { get; set; } } // 转换逻辑 var vesselData = JsonSerializer.Deserialize<VesselData>(json); // 后面的XML构建和之前完全一样...
以上代码运行后,都会生成你期望的XML结构:
<vessel> <row mmsi="538006090" imo="9700665" lat="60.87363" lon="-13.02203" /> <row mmsi="527555481" imo="970000" lat="4.57883" lon="3.76899" /> </vessel>
如果需要所有内容在一行,把ToString()改成ToString(SaveOptions.None)即可。
内容的提问来源于stack exchange,提问作者encikpiee
相关产品推荐
相关产品推荐

