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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12113014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 22:07:03  来源:igfitidea点击:

Error when deserializing xml to an object: System.FormatException Input String was not in correct format

c#xmlsilverlightxml-serializationxml-deserialization

提问by Christian

Hello and thanks in advance for the help. I am having an issue when trying to deserialize an XElement into an object using an XmlSerializer and a StringReader. My code to deserialize is this:

您好,在此先感谢您的帮助。尝试使用 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;
        }

I know the contents of the reader as revealed by the exception are:

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

<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>

And my RegisterServerObject class looks like the following:

我的 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; }

    }

And at the risk of information overload the exact exception message I am getting is this:

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

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)}

It seems there is an issue with converting the value of an xml element, ParentID maybe, into an int in order to instantiate the class, but I am not sure why that would be. Thank you in advance for the help!

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

采纳答案by carlosfigueira

The problem is that the property GroupIDis declared as an integer, but its value is empty (<GroupID/>). One solution is to change the XML so that the value for that element is a valid integer:

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

<GroupID>0</GroupID>

Another solution would be to deserialize that value as a string, and convert to an integer which users of the type may consume:

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

    [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; }
    }

回答by Dan Ellis

Could it be the GroupID that it's having issues with. Since no value for GroupID is provided, I believe it tries to pass it as a string.Emptywhich obviously wouldn't set to an intproperty.

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

You could try the following:

您可以尝试以下操作:

[XmlIgnore]
public int GroupID 
{
    get { !string.IsNullOrEmpty(GroupIDAsText) ? int.Parse(GroupIDAsText) : 0; }
    set { GroupID = value; }
}

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

.

.

回答by user854301

First you need to set XmlIgnoreattribute for GroupIDproperty

首先,你需要设置XmlIgnore的属性GroupID属性

[XmlRoot("Server")]
public class RegisterServerObject
{
   . . .
   [XmlIgnore]
   public int GroupID { get; set; }
   . . .
}

then you can create adapter that you will use for deserialization:

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

[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;
        }
    }
}

and finaly I have modified DeserializeSingleServerFromXmlmethod a bit

最后我DeserializeSingleServerFromXml稍微修改了方法

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