0

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!

  • Seems like here is your answer http://stackoverflow.com/questions/20995865/deserializing-json-to-abstract-class Eventually your own implementation: https://blog.codeinside.eu/2015/03/30/json-dotnet-deserialize-to-abstract-class-or-interface/ – Mariusz Apr 20 '17 at 15:05
  • You have [`CanRead`](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonConverter_CanRead.htm) returning false so of course your converter's `ReadJson()` is not called. For an example of what you seem to want to do, see [Json.Net Serialization of Type with Polymorphic Child Object](http://stackoverflow.com/q/29528648/3744182) or [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182). – dbc Apr 20 '17 at 16:27

0 Answers0