如何使用C#反序列化REST API返回JSON中的指定嵌套部分?
处理SOAP转JSON的嵌套响应反序列化问题
问题描述
我的C#程序调用REST API后,收到的响应是由SOAP XML转换而来的JSON格式,嵌套结构如下:
{ "soap:Envelope": { "@xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/", "soap:Header": { "omni:To": "http://www.w3.org/2005/08/tset/usr", "omni:From": { "omni:Address": "https://myweb.test/1UNIW" }, "omni:Action": "http://webservices.apitest.com/1UNIW", "omni:MessageID": "j00012", "omnii:Session": { "omnii:SecurityToken": "2S8BN3BPJMSHQK4OYKZRODFW3" } }, "soap:Body": { "MyFunct": { "@xmlns": "http://xml.test.com/1UNIW", "replyInfo": { "status": { "tierTypeInfo": "IJK" } }, "FleetIndex": [ { "groupOfObject": { "propDetail": {}, "itemDetails": [ { "ietmInformation": { "itemDateTime": { "dateOfDeparture": "270224" }, "itemNumber": "2057" } } ] } } ], "serviceCoverageInfoGrp": { "itemNumberInfo": { "itemNumber": { "number": "1" } } } } } } }
我尝试用Newtonsoft.Json反序列化:
var v = JsonConvert.DeserializeObject<ResultResponse>(jsonmessage);
但仅针对FleetIndex创建了ResultResponse类,反序列化失败,寻求最佳处理方案。
解决方案
核心问题
反序列化失败的根源是ResultResponse只匹配了FleetIndex节点,但JSON是多层嵌套结构(根节点为soap:Envelope,目标数据在soap:Body.MyFunct.FleetIndex),必须匹配完整层级或直接提取目标节点。
方案一:完整映射层级类结构
按JSON的嵌套关系创建对应C#类,用[JsonProperty]特性处理带冒号的键名:
// 根节点类 public class SoapEnvelope { [JsonProperty("soap:Envelope")] public EnvelopeContent Envelope { get; set; } } public class EnvelopeContent { [JsonProperty("@xmlns:soap")] public string XmlnsSoap { get; set; } [JsonProperty("soap:Header")] public SoapHeader Header { get; set; } [JsonProperty("soap:Body")] public SoapBody Body { get; set; } } public class SoapBody { [JsonProperty("MyFunct")] public MyFunctContent MyFunct { get; set; } } public class MyFunctContent { [JsonProperty("@xmlns")] public string Xmlns { get; set; } [JsonProperty("FleetIndex")] public List<FleetIndexItem> FleetIndex { get; set; } // 其他不需要的字段可忽略,Newtonsoft.Json会自动跳过 } // FleetIndex相关类 public class FleetIndexItem { [JsonProperty("groupOfObject")] public GroupOfObject GroupOfObject { get; set; } } public class GroupOfObject { [JsonProperty("propDetail")] public object PropDetail { get; set; } // 空对象用object接收 [JsonProperty("itemDetails")] public List<ItemDetail> ItemDetails { get; set; } } public class ItemDetail { [JsonProperty("ietmInformation")] // 注意JSON中的拼写(少了字母t),必须严格匹配 public ItemInformation ItemInformation { get; set; } } public class ItemInformation { [JsonProperty("itemDateTime")] public ItemDateTime ItemDateTime { get; set; } [JsonProperty("itemNumber")] public string ItemNumber { get; set; } } public class ItemDateTime { [JsonProperty("dateOfDeparture")] public string DateOfDeparture { get; set; } }
反序列化时:
var envelope = JsonConvert.DeserializeObject<SoapEnvelope>(jsonmessage); var targetFleetData = envelope.Envelope.Body.MyFunct.FleetIndex;
方案二:直接提取目标节点(轻量方案)
如果仅需要FleetIndex数据,可使用JObject直接定位,避免创建大量冗余类:
// 仅需创建FleetIndex相关的类(同方案一中的FleetIndexItem及下级类) var jObj = JObject.Parse(jsonmessage); var fleetIndex = jObj["soap:Envelope"]["soap:Body"]["MyFunct"]["FleetIndex"] .ToObject<List<FleetIndexItem>>();
关键注意事项
- 严格匹配JSON键名:比如原JSON中的
ietmInformation(拼写错误),类的JsonProperty必须完全一致。 - 空对象处理:
propDetail这类空对象可用object或自定义空类接收,避免反序列化报错。 - 确保类属性为
public,Newtonsoft.Json无法访问私有属性。
内容的提问来源于stack exchange,提问作者Ullan
相关产品推荐
相关产品推荐

