Я получаю XML из API Rails, но при попытке его десериализации я продолжаю получать сообщение об ошибке «Строка '' не является допустимым значением AllXsd».
Я чувствую, что это должно быть очень просто и тривиально, и что мне просто не хватает какого-то или другого атрибута, связанного с XML, но я ничего не нахожу при поиске в Google. Все примеры, похоже, используют строку для значения Date-Time, а затем выполняют внутренний анализ, чтобы получить фактическое значение DateTime, допускающее значение NULL. Это сработает, но выглядит беспорядочно и, вероятно, будет выглядеть странно, когда кто-то увидит его в следующий раз, и в этот момент они, вероятно, попытаются заменить его простым свойством и либо пропустят значение null во время тестирования, либо застрянут там, где я сейчас.
Прошу прощения за многословие следующего примера, но я попытался сократить его до наименьшего количества кода, связанного с нашей фактической реализацией.
class Program
{
static void Main(string[] args)
{
var samples = new Dictionary<string, DateTime?>{
{ // from Rails with populated datetime value
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<response>\r\n <latest-playing-at type=\"datetime\">2016-07-22T15:24:22+00:00</latest-playing-at>\r\n</response>\r\n"
,new DateTime(2016,07,22,17,24,22,DateTimeKind.Local)},
{ // from Rails with nil datetime value (THIS IS THE CASE I CARE ABOUT)
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<response>\r\n <latest-playing-at nil=\"true\"/>\r\n</response>\r\n"
,(DateTime?)null},
{ // (Test) Serialized from dotnet with null value
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<response xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <latest-playing-at xsi:nil=\"true\" />\r\n</response>"
,(DateTime?)null},
};
foreach (var sample in samples)
{
var xml = sample.Key;
var expected = sample.Value;
try
{
var testClass = DeserializeFromString<TestClass>(xml);
Console.WriteLine("Expected / Actual : {0} / {1}", expected, testClass.LatestPlayingAt);
Console.WriteLine(
DateTime.Equals(expected, testClass.LatestPlayingAt) ? "OK" : "Different" // ok to be different depening on time zones
);
}
catch (Exception exc)
{
Console.WriteLine("Error: {0}", exc.Message);
Console.WriteLine(exc);
}
}
Console.ReadKey(true);
}
public static T DeserializeFromString<T>(string inputXML)
{
using (MemoryStream inStream = new MemoryStream(new UTF8Encoding(false).GetBytes(inputXML)))
{
T result = DeserializeFromStream<T>(inStream);
return result;
}
}
public static T DeserializeFromStream<T>(Stream inStream)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(inStream);
}
}
[XmlRoot("response")]
public class TestClass
{
//[XmlElement("latest-playing-at")] // The string '' is not a valid AllXsd value.
//[XmlElement("latest-playing-at", Type = typeof(DateTime?))] // The string '' is not a valid AllXsd value.
//[XmlElement("latest-playing-at", Type = typeof(DateTime?), IsNullable = true)] // The string '' is not a valid AllXsd value.
//[XmlElement("latest-playing-at", Type = typeof(Nullable<DateTime>), IsNullable = true, Form = XmlSchemaForm.None)] // The string '' is not a valid AllXsd value.
[XmlElement("latest-playing-at", Type = typeof(Nullable<DateTime>), IsNullable = true, Form = XmlSchemaForm.Unqualified)] // The string '' is not a valid AllXsd value.
public DateTime? LatestPlayingAt { get; set; }
}