将 xml 反序列化为对象时出错:System.FormatException 输入字符串格式不正确

Posted

技术标签:

【中文标题】将 xml 反序列化为对象时出错:System.FormatException 输入字符串格式不正确【英文标题】:Error when deserializing xml to an object: System.FormatException Input String was not in correct format 【发布时间】:2012-08-20 05:32:59 【问题描述】:

您好,提前感谢您的帮助。 尝试使用 XmlSerializer 和 StringReader 将 XElement 反序列化为对象时遇到问题。我的反序列化代码是这样的:

/*deseierialize a single RegisterServerObject instance from xml*/
        static RegisterServerObject DeserializeSingleServerFromXml(XElement serverElement)
        
            XmlSerializer deserializer = new XmlSerializer(typeof(RegisterServerObject));
            RegisterServerObject server;
            using (var reader = new StringReader(serverElement.ToString()))
                server = (RegisterServerObject)deserializer.Deserialize(reader);

            return server;
        

我知道异常所揭示的读者内容是:

<Server>
  <ServerID>11</ServerID>
  <GroupID />
  <ParentID>15</ParentID>
  <ServerName>IAProd1</ServerName>
  <User>admin</User>
  <UID>123</UID>
  <PWD>password</PWD>
  <Domain>InputAccel</Domain>
  <Location>Left</Location>
  <AssociatedModules>
    <Module>
      <ModId>1</ModId>
      <ServerId>11</ServerId>
      <ModName>TestModA</ModName>
      <ModuleStatus>1</ModuleStatus>
    </Module>
    <Module>
      <ModId>2</ModId>
      <ServerId>11</ServerId>
      <ModName>TestModB</ModName>
      <ModuleStatus>1</ModuleStatus>
    </Module>
    <Module>
      <ModId>9</ModId>
      <ServerId>11</ServerId>
      <ModName>TestModI</ModName>
      <ModuleStatus>1</ModuleStatus>
    </Module>
    <Module>
      <ModId>10</ModId>
      <ServerId>11</ServerId>
      <ModName>TestModJ</ModName>
      <ModuleStatus>1</ModuleStatus>
    </Module>
  </AssociatedModules>
</Server>

我的 RegisterServerObject 类如下所示:

[XmlRoot("Server")]
    public class RegisterServerObject
    
        public RegisterServerObject()  

        public int ServerID  get; set; 

        public int GroupID  get; set; 

        public int ParentID  get; set; 

        public string ServerName  get; set; 

        public string User  get; set; 

        public int Uid  get; set; 

        public string Domain  get; set; 

        public string Location  get; set; 

        public List<RegisterModuleObject> AssociatedModules  get; set; 

    

冒着信息过载的风险,我得到的确切异常消息是这样的:

System.InvalidOperationException: There is an error in XML document (4, 4). ---> System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Xml.XmlConvert.ToInt32(String s)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderRegisterServerObject.Read3_RegisterServerObject(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderRegisterServerObject.Read4_Server()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, Object events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
   at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
   at SL_xMonitor_Frontend_RefactorV1.Views.RegisteringNewChildWindowV2.DeserializeSingleServerFromXml(XElement serverElement)
   at SL_xMonitor_Frontend_RefactorV1.Views.RegisteringNewChildWindowV2.modXmlClient_getAssociatedModulesCompleted(Object sender, getAssociatedModulesCompletedEventArgs e)
   at SL_xMonitor_Frontend_RefactorV1.XMLServersAndModulesServiceReference.XMLTablesAndModulesServiceClient.OngetAssociatedModulesCompleted(Object state)

为了实例化类,将 xml 元素的值(可能是 ParentID)转换为 int 似乎存在问题,但我不确定为什么会这样。提前感谢您的帮助!

【问题讨论】:

为什么将XElement 传递给方法而不是XDoxument 现在代码的编写方式,相关的 XDocument 实例由多个 条目和它们自己的模块组成,我没有运气尝试将整个东西反序列化为一个类,所以我想我会分解它:) 【参考方案1】:

可能是它遇到问题的 GroupID。由于没有提供 GroupID 的值,我相信它会尝试将其作为 string.Empty 传递,这显然不会设置为 int 属性。

您可以尝试以下方法:

[XmlIgnore]
public int GroupID 

    get  !string.IsNullOrEmpty(GroupIDAsText) ? int.Parse(GroupIDAsText) : 0; 
    set  GroupID = value; 


[XmlAttribute("GroupID")
public int GroupIDAsText  get; set; 

.

【讨论】:

【参考方案2】:

问题是属性GroupID 被声明为整数,但其值为空(&lt;GroupID/&gt;)。一种解决方案是更改 XML,使该元素的值是一个有效的整数:

<GroupID>0</GroupID>

另一种解决方案是将该值反序列化为字符串,并转换为该类型的用户可以使用的整数:

    [XmlRoot("Server")]
    public class RegisterServerObject
    
        public RegisterServerObject()  

        public int ServerID  get; set; 

        [XmlIgnore]
        public int GroupID  get; set; 
        [XmlElement(ElementName = "GroupID")]
        public string GroupIDStr
        
            get
            
                return this.GroupID.ToString();
            
            set
            
                if (string.IsNullOrEmpty(value))
                
                    this.GroupID = 0;
                
                else
                
                    this.GroupID = int.Parse(value);
                
            
        

        public int ParentID  get; set; 

        public string ServerName  get; set; 

        public string User  get; set; 

        public int Uid  get; set; 

        public string Domain  get; set; 

        public string Location  get; set; 

        [XmlArray(ElementName = "AssociatedModules")]
        [XmlArrayItem(ElementName = "Module")]
        public List<RegisterModuleObject> AssociatedModules  get; set; 
    

    public class RegisterModuleObject
    
        public int ModId  get; set; 
        public int ServerId  get; set; 
        public string ModName  get; set; 
        public int ModuleStatus  get; set; 
    

【讨论】:

感谢您快速而完整的回复。它解决了抛出的异常并导致了大多数预期的行为。但是,创建的 RegisterServerObject 没有从 xml 填充其 AssociatedModules 列表属性。你知道为什么会这样吗,如果我可以在代码中更改一些东西来实现这一点?或者如果它只是我反序列化它的方式的限制?再次感谢您的帮助 由于 XML 中的名称和类型名称不匹配,您没有在关联的模块列表中填充模块。您可以使用[XmlArray][XmlArrayItem] 装饰列表属性来定义预期的名称(正如我在更新的答案中所做的那样)或使用[XmlType] 来更改RegisterModuleObject 类的XML 名称。 哇哦,真漂亮。我已经更正了名称不匹配,但只使用了 [XmlElement] 标签,而不是您指出的 [XmlArray][XmlArrayItem] 标签。再次感谢您的帮助,现在行为正常。哇,xml 反序列化非常漂亮。【参考方案3】:

首先你需要为GroupID属性设置XmlIgnore属性

[XmlRoot("Server")]
public class RegisterServerObject

   . . .
   [XmlIgnore]
   public int GroupID  get; set; 
   . . .

然后您可以创建将用于反序列化的适配器:

[XmlRoot("Server")]
public class RegisterServerObjectAdapter : RegisterServerObject

    [XmlElement("GroupID")]
    public string GroupIDNew
    
        get  return GroupID.ToString(); 
        set
        
            int outInt;
            int.TryParse(value, out outInt);
            GroupID = outInt;
        
    

最后我稍微修改了DeserializeSingleServerFromXml 方法

    static RegisterServerObject DeserializeSingleServerFromXml(XDocument serverElement)
    
        var deserializer = new XmlSerializer(typeof(RegisterServerObjectAdapter));
        return (RegisterServerObject)deserializer.Deserialize(serverElement.CreateReader(ReaderOptions.OmitDuplicateNamespaces));
    

【讨论】:

以上是关于将 xml 反序列化为对象时出错:System.FormatException 输入字符串格式不正确的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 文件反序列化为 C# 类对象时出错

XML 文档中存在错误 (0, 0) - 将 XML 反序列化为对象时出错

将 xml 反序列化为对象时出错:System.FormatException 输入字符串格式不正确

使用 DataContractSerializer 反序列化 XML 时出错

将字符串反序列化为 *.proto 中定义的对象时出错?

将 xml 反序列化为 c# 对象时,XML 文档 (2, 2) 出现错误