Невозможно десерализовать объект, имеющий список <T>, где T получен из интерфейса - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть объект типа Job, и я успешно сериализовал его в файл JSON, но у меня возникает эта проблема

Не удалось привести или преобразовать из System.String в qConnector_v2._0.Model.Job

Вот как я делаю сериализацию:

_Job.Tasks.Add(new Email());
_Job.Tasks.Add(new UNC());
_Job.Tasks.Add(new FTP());
_Job.Tasks.Add(new WebApi());
_Job.Tasks.Add(new WebService());
_Job.Tasks.Add(new StoredProcedure());
_Job.Tasks.Add(new Odbc());
Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
serializer.Converters.Add(new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter());
serializer.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
serializer.Formatting = Newtonsoft.Json.Formatting.Indented;

using (StreamWriter sw = new StreamWriter(@"C:\Temp\res.json"))
using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
{
    serializer.Serialize(writer, _Job, typeof(Model.Job));
}

Вот как я делаю десериализацию:

Model.Job obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Model.Job>(File.ReadAllText(@"C:\Temp\res.json"), new Newtonsoft.Json.JsonSerializerSettings
{
    TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto,
});

Более подробно, вот структура класса:

Основной класс - Работа

class Job : IDisposable
{
    private Guid _ID;
    public Job()
    {
        ID = Guid.NewGuid();

    }
    public Guid ID { get { return _ID; } internal set { _ID = value; } }
    public DateTime ScheduledTime { get; set; }
    public Configurations Configuration { get; set; }
    public Scheduler Scheduler { get; set; }
    public List<Task> Tasks { get; set; }

    #region IDisposable Support
    private bool disposedValue = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and  a finalizer below.
            // TODO: set large fields to null.

            disposedValue = true;
        }
    }

    // TODO:  a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
    ~Job()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(false);
    }

    // This code added to correctly implement the disposable pattern.
    public void Dispose()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
        // TODO: uncomment the following line if the finalizer is overridden above.
        // GC.SuppressFinalize(this);
    }
    #endregion
}

и вот объявление Task, и я получил больше типов, если этот интерфейс

public interface Task : IDisposable
{
    //public Task() { }
    string Title { get; set; }
    bool ExecuteTask();/* { return true; }*/
    bool? NotifyOnSuccess { get; set; }
    bool? NotifyOnFailure { get; set; }


}

и вот список Типов, полученных из интерфейса Задачи:

Task Types Derived from Interface Task

Вот пример одного из классов, полученных из типа задачи:

public class Email : Task
{     
    public string Recipients { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
    public string AttachmentPath { get; set; }
    public string From { get; set; }
    public  string Title { get; set; }
    public  bool? NotifyOnSuccess { get; set; }
    public  bool? NotifyOnFailure { get; set; }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    public  bool ExecuteTask()
    {
        return true;
    }

}

Вот вывод JSON.

Примечание: значения полей в классе Планировщика назначены, но я не знаю, почему они отображаются с разными значениями в выводе.

{
  "ID": "9ebcec6c-8adb-421d-882b-da51b106f14b",
  "ScheduledTime": new Date(
    1536674974648
  ),
  "Configuration": {
    "CommunicationLanguage": 0,
    "NotifyBy": 0,
    "RelayServer": "Relay Server",
    "Port": "Port",
    "Username": "Username",
    "Passwoprd": "Password",
    "FromAddress": "From address",
    "Recipients": "",
    "StoredProcedureName": "Stored procedure name",
    "ConnectionString": "Connection String",
    "ProfileName": "Profile name"
  },
  "Scheduler": {
    "ScheduleType": 0,
    "Occurs": 0,
    "RecursEvery": 1,
    "OccursOnceAt": "17:04:47.3262587",
    "DurationStartDate": new Date(
      1536613487322
    ),
    "DurationEndDate": new Date(
      1536613487318
    ),
    "dayOrderInMonth": 0,
    "DayName": 0
  },
  "Tasks": [
    {
      "$type": "qConnector_v2._0.Model.WebApi, qConnector v2.0",
      "BaseURL": "d",
      "Route": "d",
      "Params": "d",
      "Header": "d",
      "NotifyOnSuccess": true,
      "NotifyOnFailure": false,
      "Title": "api Test"
    },
    {
      "$type": "qConnector_v2._0.Model.WebService, qConnector v2.0",
      "Title": "ws test",
      "Url": "",
      "Name": "",
      "Method": "",
      "NotifyOnSuccess": true,
      "NotifyOnFailure": false
    },
    {
      "$type": "qConnector_v2._0.Model.Odbc, qConnector v2.0",
      "Title": "odbc",
      "DataSource": "Data source",
      "Database": "Database",
      "User": "Username",
      "Password": "Password",
      "Type": "Odbc Type",
      "Query": "QUERY",
      "DestinationDataSource": "Data source",
      "DestinationDatabase": "Database",
      "DestinationUsername": "Username",
      "DestinationPassword": "Password",
      "DestinationStoreProcedure": "Stored Procedure Name",
      "DestinationLocation": "UNC Destination",
      "NotifyOnSuccess": false,
      "NotifyOnFailure": true
    },
    {
      "$type": "qConnector_v2._0.Model.FTP, qConnector v2.0",
      "Title": "ftp",
      "LocalPath": "Local path",
      "Server": "Server Path",
      "Password": "Password",
      "Username": "Username",
      "Download": false,
      "Upload": true,
      "NotifyOnSuccess": true,
      "NotifyOnFailure": false
    },
    {
      "$type": "qConnector_v2._0.Model.Excel, qConnector v2.0",
      "Title": "excel",
      "Location": "UNC path to load Excel file",
      "DataSource": "Data source",
      "Database": "Database",
      "Username": "Username",
      "Password": "Password",
      "StoredProcedure": "Stored Procedure Name",
      "SheetName": "Sheet Name (optional)",
      "NotifyOnSuccess": true,
      "NotifyOnFailure": true
    },
    {
      "$type": "qConnector_v2._0.Model.UNC, qConnector v2.0",
      "Title": "unc test",
      "Type": 2,
      "Source": "Source Path",
      "Destination": "Destination Path",
      "NotifyOnSuccess": true,
      "NotifyOnFailure": true
    },
    {
      "$type": "qConnector_v2._0.Model.Email, qConnector v2.0",
      "Recipients": "recipient email,recipient email,recipient email",
      "Subject": "Subject",
      "Body": "BODY",
      "AttachmentPath": "Attachment Path",
      "From": "From",
      "Title": "email test",
      "NotifyOnSuccess": false,
      "NotifyOnFailure": true
    },
    {
      "$type": "qConnector_v2._0.Model.StoredProcedure, qConnector v2.0",
      "Title": "TITLE",
      "NotifyOnSuccess": true,
      "NotifyOnFailure": false,
      "DataSource": "Data source",
      "Database": "Database",
      "Username": "Username",
      "Password": "Password",
      "SqlCommand": "SQL Command - SP Call"
    }
  ]
}

Вот структура класса Планировщика:

public class Scheduler : IDisposable
{
    public enum SchedulerType { Recurring, OneTime };
    public enum SchedulerFrequency { Daily, Weekly, Monthly };
    public enum DayOrderInMonth { First, Second, Third, Fourth, Last };
    public DateTime? Scheduled { get; set; }
    public SchedulerType ScheduleType { get; set; }
    public DateTime? OneTimeDate { get; set; }
    public TimeSpan? OneTimeTime { get; set; }
    public SchedulerFrequency Occurs { get; set; }
    public int? RecursEvery { get; set; }
    public TimeSpan? OccursOnceAt { get; set; }
    public DateTime? DurationStartDate { get; set; }
    public DateTime? DurationEndDate { get; set; }
    public string WeekDays { get; set; }
    public List<DayOfWeek> WeekDaysList { get; set; }
    public DayOrderInMonth dayOrderInMonth { get; set; }
    public DayOfWeek DayName { get; set; }
    public int? EveryNumberOfMonth { get; set; }
    public int? DayNumberEachMonth { get; set; }
    public int? TheOptionRecursEveryMonth { get; set; }
    public int? RecursEveryWeek { get; set; }
}

1 Ответ

0 голосов
/ 12 сентября 2018

Решение было очень простым, вместо использования этого

Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
serializer.Converters.Add(new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter());
serializer.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
serializer.Formatting = Newtonsoft.Json.Formatting.Indented;

using (StreamWriter sw = new StreamWriter(@"C:\Temp\res.json"))
using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
{
    serializer.Serialize(writer, _Job, typeof(Model.Job));
}

Мне нужно было всего лишь удалить следующую строку:

serializer.Converters.Add (new Newtonsoft.Json.Converters.JavaScriptDateTimeConverter ());

Таким образом, код будет:

Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
serializer.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
serializer.Formatting = Newtonsoft.Json.Formatting.Indented;

using (StreamWriter sw = new StreamWriter(@"C:\Temp\res.json"))
using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
{
    serializer.Serialize(writer, _Job, typeof(Model.Job));
}
...