C # Сложный объект, содержащий словарь Проблема десериализации XML

#c# #xml #xml-deserialization

#c# #xml #xml-десериализация

Вопрос:

XML, подлежащий десериализации:

 <CheckOnlineStatus xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Lifecare.LIS.Integration.Hyland.Models">
  <Database>string</Database>
  <InstancesStillNearline>0</InstancesStillNearline>
  <SeriesLocationMap xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <d2p1:KeyValueOfstringboolean>
      <d2p1:Key>test</d2p1:Key>
      <d2p1:Value>true</d2p1:Value>
    </d2p1:KeyValueOfstringboolean>
    <d2p1:KeyValueOfstringboolean>
      <d2p1:Key>test1</d2p1:Key>
      <d2p1:Value>false</d2p1:Value>
    </d2p1:KeyValueOfstringboolean>
  </SeriesLocationMap>
  <Status>string</Status>
  <StudyInstanceUID>string</StudyInstanceUID>
  <TotalClips>0</TotalClips>
  <TotalExecutionTime>0</TotalExecutionTime>
  <TotalInstances>0</TotalInstances>
</CheckOnlineStatus>
 

Используемые модели данных:

 using System.Collections.Generic;
using System.Xml.Serialization;

[XmlRoot("CheckOnlineStatus")]
/// <summary>
/// The CheckOnlineStatus entity.
/// </summary>
public class CheckOnlineStatus
{
    [XmlElement("Status")]
    /// <summary>
    /// Gets or sets the Status
    /// </summary>
    public string Status { get; set; }

    [XmlElement("Database")]
    /// <summary>
    /// Gets or sets the Database
    /// </summary>
    public string Database { get; set; }

    /// <summary>
    /// Gets or sets the StudyInstanceUID
    /// </summary>
    [XmlElement("StudyInstanceUID")]
    public string StudyInstanceUID { get; set; }

    /// <summary>
    /// Gets or sets the TotalExecutionTime
    /// </summary>
    [XmlElement("TotalExecutionTime")]
    public long TotalExecutionTime { get; set; }

    /// <summary>
    /// Gets or sets the TotalInstances
    /// </summary>
    [XmlElement("TotalInstances")]
    public int TotalInstances { get; set; }

    /// <summary>
    /// Gets or sets the TotalClips
    /// </summary>
    [XmlElement("TotalClips")]
    public int TotalClips { get; set; }

    /// <summary>
    /// Gets or sets the InstancesStillNearline
    /// </summary>
    [XmlElement("InstancesStillNearline")]
    public int InstancesStillNearline { get; set; }

    /// <summary>
    /// Gets or sets the dictionary of series location map
    /// </summary>
    [XmlElement("SeriesLocationMap")]
    public Dictionary<string, bool> SeriesLocationMap { get; set; }
}
 

Код десериализации, здесь результат выше xml в строковом формате:

 (CheckOnlineStatus)new XmlSerializer(typeof(CheckOnlineStatus)).Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(result)));
 

Я получаю ошибку ниже во время выполнения:

Не удается сериализовать файл Lifecare.LIS.Integration.NDP.Models участника.Проверьте linestatus.SeriesLocationMap системы типов.Коллекции.Generic.Dictionary`2[[System.Строка, mscorlib, Версия= 4.0.0.0, Культура = нейтральная, PublicKeyToken=b77a5c561934e089],[Система.Логическое значение, mscorlib, версия = 4.0.0.0, Культура = нейтральная, PublicKeyToken=b77a5c561934e089]], потому что он реализует IDictionary.

Я попробовал пару других вещей, но это не сработало, например. https://www.codeproject.com/Questions/716556/XML-deserialize-Attributes-to-dictionary

Может кто-нибудь, пожалуйста, помогите здесь. Спасибо.

Ответ №1:

Поскольку исключение ( InvalidOperationException с внутренним UnsupportedException ) говорит, что вы не можете просто десериализовать его в a Dictionary .

Вот один из способов преодолеть эту трудность:

Определение ключевого значения

 [Serializable]
public struct KeyValue
{
    public string Key { get; set; }
    public bool Value { get; set; }
}
 

В качестве альтернативы вы можете воспользоваться встроенным KeyValuePair<TKey, TValue>

Использование XmlArray и XmlArrayItem

 [XmlArray("SeriesLocationMap")]
[XmlArrayItem("KeyValueOfstringboolean")]
public List<KeyValue> IntermediateContainer { get; set; }
 

Используется XmlIgnore для преобразования списка в Dictionary<string, bool>

 [XmlIgnore]
public Dictionary<string, bool> SeriesLocationMap  => IntermediateContainer.ToDictionary(x => x.Key, y => y.Value);
 

Я тестировал его без пространств имен, поэтому вам нужно указать их в нужном месте, чтобы иметь возможность правильно их прочитать.


В качестве альтернативы вы можете попробовать использовать DataContractSerializer тот, который поддерживает Dictionary.

Комментарии:

1. Спасибо. DataSerializer исправил проблему для нас