【发布时间】:2018-04-20 01:49:44
【问题描述】:
我经常看到这个问题,但似乎没有人的标题真正描述了他们的问题。我从一个包含一般响应信息的 Web API 返回一个大型响应对象,以及我想要反序列化的数据对象。
完整的 XML:
<?xml version="1.0"?>
<root>
<status>
<apiErrorCode>0</apiErrorCode>
<apiErrorMessage/>
<dbErrorCode>0</dbErrorCode>
<dbErrorMessage/>
<dbErrorList/>
</status>
<data>
<modelName>ReportXDTO</modelName>
<modelData>
<id>1780</id>
<reportTitle>Access Level (select) with Door Assignment</reportTitle>
<hasParameters>true</hasParameters>
<parameters>
<dataType>STRING</dataType>
<title>Access Level:</title>
<index>1</index>
<allowMulti>true</allowMulti>
<selectSql>SELECT DISTINCT [Name] FROM dbo.[Levels] WHERE [PrecisionFlag] = '0' ORDER BY [Name] </selectSql>
<values>
<value>Door 1</value>
<used>1</used>
</values>
<values>
<value>Door 2</value>
<used>1</used>
</values>
<values>
<value>Door 3</value>
<used>1</used>
</values>
</parameters>
<sourceSql>SELECT [Name], [SData] FROM [Schedules]</sourceSql>
<report/>
</modelData>
<itemReturned>1</itemReturned>
<itemTotal>1</itemTotal>
</data>
<listInfo>
<pageIdRequested>1</pageIdRequested>
<pageIdCurrent>1</pageIdCurrent>
<pageIdFirst>1</pageIdFirst>
<pageIdPrev>1</pageIdPrev>
<pageIdNext>1</pageIdNext>
<pageIdLast>1</pageIdLast>
<itemRequested>1</itemRequested>
<itemReturned>1</itemReturned>
<itemStart>1</itemStart>
<itemEnd>1</itemEnd>
<itemTotal>1</itemTotal>
</listInfo>
</root>
我只想反序列化 modelData 元素。 modelData 对象类型是动态的,具体取决于 API 调用。
我在其他应用程序中反序列化xml,并创建了以下方法,但不知道具体如何仅获取modelData元素:
public static T ConvertXmltoClass<T>(HttpResponseMessage http, string elementName) where T : new()
{
var newClass = new T();
try
{
var doc = JsonConvert.DeserializeXmlNode(http.Content.ReadAsStringAsync().Result, "root");
XmlReader reader = new XmlNodeReader(doc);
reader.ReadToFollowing(elementName);
//The xml needs to show the proper object name
var xml = reader.ReadOuterXml().Replace(elementName, newClass.GetType().Name);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
var serializer = new XmlSerializer(typeof(T));
newClass = (T)serializer.Deserialize(stream);
}
}
catch (Exception e)
{
AppLog.LogException(System.Reflection.MethodBase.GetCurrentMethod().Name, e);
}
return newClass;
}
我现在已经多次更新这个帖子,以保持最新状态。我开始使用第一个解决方案对其进行更新。但该解决方案本身并不能解决问题。使用现在的代码,我没有任何例外,但不要将 xml 反序列化为我的对象。相反,我得到了一个新的空白对象。想法?
虽然对象类型可以更改,但这是我正在处理的当前对象:(请注意,我在 web API 中的 modelData 中反序列化了确切的 xml)
namespace WebApiCommon.DataObjects
{
[Serializable]
public class ReportXDto
{
public ReportXDto()
{
Parameters = new List<ReportParameterXDto>();
}
public int Id { get; set; }
public string ReportTitle { get; set; }
public bool HasParameters { get; set; } = false;
public List<ReportParameterXDto> Parameters { get; set; }
public string SourceSql { get; set; }
public DataTable Report { get; set; }
}
[Serializable]
public class ReportXDto
{
public ReportXDto()
{
Parameters = new List<ReportParameterXDto>();
}
public int Id { get; set; }
public string ReportTitle { get; set; }
public bool HasParameters { get; set; } = false;
public List<ReportParameterXDto> Parameters { get; set; }
public string SourceSql { get; set; }
public DataTable Report { get; set; }
}
[Serializable]
public class ReportParameterValuesXDto
{
public string Value { get; set; } = "";
public bool Used { get; set; } = false;
}
}
【问题讨论】:
-
我对你想做什么有点困惑。为什么要从 JSON 转换为 XML?为什么不直接从 JSON 反序列化?另外,为什么是
XmlDocument而不是XDocument? -
我从中获取数据的 Web API 返回一个 json 响应。从 json 到 XmlDocument 的反序列化效果很好,我在许多其他应用程序中使用该方法。这个问题是独一无二的,因为 API 响应中返回的 modelData 是 XML。
-
只要我可以将 modelData 反序列化为我的 T 对象,我就不再关心我必须实施什么解决方案。
-
您可以使用来自Deserialize object property with StringReader vs XmlNodeReader 和c#, XML How to cycle through an XML node fetched with XMLNode.SelectSingleNode 的
ProperXmlNodeReader直接从XmlNode反序列化。或者,如果您切换到 LINQ to XML,您可以使用XObjectExtensions.Deserialize<T>(this XContainer element)from Changing type of element in XML Serialization。 -
那么,现在到底是什么问题呢?是不是元素名称
<modelData>与您尝试反序列化的T类型的根元素名称不匹配?您能否提供一个 minimal reproducible example,其中包含您尝试反序列化的类型T?
标签: c# xml serialization xmlserializer