currently, we are trying to deserialize a json string that contains an ICollection of an abstract class. After doing some research, I decided to use a converter, but I still can't seem to get past the following error:
Could not create an instance of type WorkflowActivity. Type is an interface or abstract class and cannot be instantiated. Path 'activities[0].controllerName
This is the code I am using:
var jsonString = "{\"activities\":[{\"controllerName\":\"index\",\"actionName\":\"Index\",\"routeValueByName\":{},\"key\":\"9a9c50c5-ae82-40be-89dc-e9676cf731fb\",\"OwnerUserId\":\"ff9f2cfe-5523-4844-bc97-f705f40de2f5\",\"nextActivityChooserType\":\"FieldComparisonActivityChooser\",\"nextActivityChooserConfig\":\"{\"expressions\":[{\"code\":\"wfQuestion.Valid == true\",\"workflowActivityKey\":\"B1\"},{\"code\":\"wfQuestion.Valid == false\",\"workflowActivityKey\":\"B2\"}]}\",\"emailTemplateId\":1},{\"controllerName\":\"index\",\"actionName\":\"Index\",\"routeValueByName\":{},\"key\":\"B1\",\"OwnerUserId\":\"9a9c50c5-ae82-40be-89dc-e9676cf731fb\",\"nextActivityChooserType\":\"FieldComparisonActivityChooser\",\"nextActivityChooserConfig\":\"{\"expressions\":[{\"code\":\"wfQuestion.Valid == true\",\"workflowActivityKey\":\"B1\"},{\"code\":\"wfQuestion.Valid == false\",\"workflowActivityKey\":\"B2\"}]}\",\"emailTemplateId\":1},{\"controllerName\":\"index\",\"actionN\r\name\":\"Index\",\"routeValueByName\":{},\"key\":\"B2\",\"OwnerUserId\":\"00188258-4467-484f-8c59-8e0da3e991f1\",\"nextActivityChooserType\":\"FieldComparisonActivityChooser\",\"nextActivityChooserConfig\":\"\",\"emailTemplateId\":1}]}";
var deserialized = WorkflowDescription.Deserialize(jsonString);
WorkflowDescription class:
internal class WorkflowDescription : IWorkflowDescription
{
public string ToJson()
{
return JsonConvert.SerializeObject(this);
}
public static WorkflowDescription Deserialize(string json)
{
return JsonConvert.DeserializeObject<WorkflowDescription>(json, new WorkflowDescriptionConverter(typeof(WorkflowDescription), typeof(ICollection<WorkflowActivity>), typeof(WorkflowActivity)));
}
//this is the collection of abstract class I am having trouble with
[JsonProperty("activities")]
public ICollection<WorkflowActivity> Activities { get; set; }
}
WorkflowDescription Interface:
public interface IWorkflowDescription
{
ICollection<WorkflowActivity> Activities { get; set; }
}
WorkflowActivity base class:
public abstract class WorkflowActivity
{
[JsonProperty("key")]
public string WorkflowActivityKey { get; set; }
[JsonProperty("OwnerUserId")]
public string OwnerUserId { get; set; }
[JsonIgnore]
public Type NextActivityChooserType
{
get { return Type.GetType(NextActivityChooserTypeName); }
}
[JsonProperty("nextActivityChooserType")]
public string NextActivityChooserTypeName { get; set; }
[JsonProperty("nextActivityChooserConfig")]
public string NextActivityChooserConfig { get; set; }
[JsonProperty("emailTemplateId")]
public int EmailTemplateId { get; set; }
}
WebActionWorkflowActivity class. (This is what I am trying to convert to in my converter)
public class WebActionWorkflowActivity : WorkflowActivity
{
[JsonProperty("controllerName")]
public string ControllerName { get; set; }
[JsonProperty("actionName")]
public string ActionName { get; set; }
[JsonProperty("routeValueByName")]
public IDictionary<string, object> RouteValueByName { get; set; }
}
WorkflowDescriptionConverter class *Note: I'm not terribly concerned with what's going on in ReadJson and WriteJson at the moment. I have placed breakpoints there, as right now I am just seeing if I can get to those methods and will refine when I get past the error above.
public class WorkflowDescriptionConverter : JsonConverter
{
private readonly Type[] _types;
public WorkflowDescriptionConverter(params Type[] types)
{
_types = types;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
JObject jo = (JObject)t;
List<WorkflowActivity> convertedActivities = new List<WorkflowActivity>();
foreach (var activity in jo["activities"])
{
if (activity.GetType().GetProperty("controllerName") != null)
{
convertedActivities.Add(new WebActionWorkflowActivity
{
ActionName = activity["actionName"].ToString(),
ControllerName = activity["controllerName"].ToString()
});
}
}
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return _types.Any(t => t == objectType);
}
public override bool CanRead
{
get { return false; }
}
public override bool CanWrite
{ get { return true; } }
}
}
I was able to confirm that CanConvert does return true in my converter for all types passed in. Thanks!