TransWikia.com

XmlSerializer с AttributeName возвращает null

Stack Overflow на русском Asked on December 25, 2021

Есть некий xml. Примерно такой:

<?xml version="1.0" encoding="UTF-8"?>
<GetOrdersResponse 
  xmlns="urn:ebay:apis:eBLBaseComponents">
  <Timestamp>2020-07-23T17:25:06.492Z</Timestamp>
  <OrderArray>
    <Order>
      <OrderID>0000000000-111111111111</OrderID>
      <OrderStatus>Completed</OrderStatus>
      <CreatedTime>2020-07-22T07:09:19.000Z</CreatedTime>
    </Order>
</GetOrdersResponse>

Преобразовав это дело в классы C# имею примерно это:

    // Примечание. Для запуска созданного кода может потребоваться NET Framework версии 4.5 или более поздней версии и .NET Core или Standard версии 2.0 или более поздней.
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:ebay:apis:eBLBaseComponents")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:ebay:apis:eBLBaseComponents", IsNullable = false)]
    public partial class GetOrdersResponse
    {

        private DateTime timestampField;
        
        private GetOrdersResponseOrderArray orderArrayField;

        /// <remarks/>
        public GetOrdersResponseOrderArray OrderArray
        {
            get
            {
                return this.orderArrayField;
            }
            set
            {
                this.orderArrayField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
        public DateTime Timestamp
        {
            get
            {
                return this.timestampField;
            }
            set
            {
                this.timestampField = value;
            }
        }
    }

Разумеется, классы автоматически сгенерированы.

И проблема заключается в том, что при запуске такого кода и попытке десериализации xml, я получаю исключение String "2020-07-23T17:25:06.492Z" was not recognized as a valid DateTime.

Начитавшись в интернетах всяких советов, я изменил мой C# класс следующим образом:

    // Примечание. Для запуска созданного кода может потребоваться NET Framework версии 4.5 или более поздней версии и .NET Core или Standard версии 2.0 или более поздней.
    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:ebay:apis:eBLBaseComponents")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:ebay:apis:eBLBaseComponents", IsNullable = false)]
    public partial class GetOrdersResponse
    {
        //[XmlAttribute(AttributeName = "Timestamp")]
        //[XmlAttribute("Timestamp")]
        //[SoapAttribute(DataType = "string", AttributeName = "Timestamp")]
        // Ни одна из строк выше не помогла
        private string timestampField; // пробовал ещё это поле
        // делать public и приписать { get; set; } - тот же результат
        
        private GetOrdersResponseOrderArray orderArrayField;

        /// <remarks/>
        public GetOrdersResponseOrderArray OrderArray
        {
            get
            {
                return this.orderArrayField;
            }
            set
            {
                this.orderArrayField = value;
            }
        }

        /// <remarks/>
        //[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
        [XmlIgnore]
        public System.DateTime Timestamp
        {
            get 
            { 
                if (string.IsNullOrEmpty(this.timestampField)) 
                { 
                    return new DateTime(); 
                } 
                else 
                {
                    return DateTime.ParseExact(this.timestampField, "yyyy-MM-ddTHH:mm:ss.fffZ", System.Globalization.CultureInfo.InvariantCulture);
                } 
            }
            set
            {
                this.timestampField = value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
            }
        }

    }

Результат моих стараний – timestampField всегда null. Если я менял timestampField на Timestamp и убирал все XmlAttribute, то строка приходила правильная. Выходит, при использовании XmlAttribute у меня всегда возвращается null. И вот тут я уже не имею представления, почему так происходит, и как это решить

P.S. В Order (а также классах, что не попали в данный вопрос) с датой-временем ровно та же беда

UPD: На всякий случай также приложу метод, вызываемый при десериализации:

    public object ConvertXMLStringToObject(Type typeForConverter, string text)
    {
        try
        {
            var xdoc = XDocument.Parse(text);
            XmlSerializer s = new XmlSerializer(typeForConverter);
            return s.Deserialize(xdoc.CreateReader());
        }
        catch
        {
            return null;
        }
    }

Вызывается данный метод такой строкой:

  var result = (GetOrdersResponse)new XMLConverter().ConvertXMLStringToObject(typeof(GetOrdersResponse), await response.Content.ReadAsStringAsync());

One Answer

Я сгенерировал в Студии код по представленному xml. Он отличается от вашего только отсутствием атрибута [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] на свойстве Timestamp.

Просто уберите этот атрибут. В нём явно указано, что ожидается тип "date" - только дата, без времени.


Откуда мог взяться этот атрибут?

Вероятно, вы использовали другой xml при генерации, в котором не было времени в элементе Timestamp.

Другая возможная причина: генераторы классов по xml/json вполне могут ошибаться и генерировать не совсем валидный код. Поэтому ручная корректировка вполне допустима. Точный результат может обеспечить только генерация по схеме (XmlSchema), в который прописаны все типы данных.

Answered by Alexander Petrov on December 25, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP