0

I have a web method that returns a collection of objects which have a property that is an abstract class. There are three types that derive from the abstract class.

public enum VehicleType { Train, Truck, Boat }

public abstract class Vehicle
{
    public VehicleType VehicleType { get; set; }
    ...
}

public class Train : Vehicle { ... }
public class Truck : Vehicle { ... }
public class Boat : Vehicle { ... }
public class Shipment
{
    public Vehicle TransportVehicle { get; set; }
}
[HttpGet]
[Route("{customerId}/shipments")]
public async Task<ActionResult<ShipmentsResponse>> GetCustomerShipments(intcustomerId, CancellationToken cancellationToken)
{
    ...
    // Returns a ShipmentResponse which contains a collection of Shipment objects
}

When the result is received by the client, JSON.NET attempts to deserialize the collection and throws this exception:

Could not create an instance of type Management.Domain.Models.Vehicle. Type is an interface or abstract class and cannot be instantiated. Path 'data.shipments[0].vehicle.vehicleType', line 1, position 462.

So I figured I could use a CustomCreationConverter for the Vehicle type:

public class VehicleConverter : CustomCreationConverter<Vehicle>
{
    private VehicleType _currentVehicleType;

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.ReadFrom(reader);
        _currentScheduleType = jObject["VehicleType"].ToObject<UserScheduleType>();
        return base.ReadJson(jObject.CreateReader(), objectType, existingValue, serializer);
    }

    public override VehicleCreate(Type objectType)
    {
        switch (_currentVehicleType)
        {
            case VehicleType.Train:
                return new Train();
            case VehicleType.Truck:
                return new Truck();
            case VehicleType.Boat:
                return new Boat();
            default:
                throw new NotImplementedException();
        }
    }
}

...but this code is never hit. Can anyone shed some light on how I can resolve this? Thanks for any advice!

Easy Rhino
  • 63
  • 1
  • 6
  • Don't you want to pass `_currentScheduleType` to `base.ReadJson()`, i.e. `base.ReadJson(jObject.CreateReader(), _currentScheduleType, existingValue, serializer);`? Also, `_currentVehicleType` should be a variable not a field since it isn't used outside the scope of `ReadJson()`. – dbc Mar 21 '21 at 18:06
  • Does this answer your question? [C# JSON Deserialization : Type is an interface or abstract class and cannot be instantiated](https://stackoverflow.com/questions/37069574/c-sharp-json-deserialization-type-is-an-interface-or-abstract-class-and-cannot) – Orace Mar 21 '21 at 18:07
  • Newtonsoft's `CustomCreationConverter` is not a particularly good base class to use here. Better to roll your own as shown in [this answer](https://stackoverflow.com/a/8031283/3744182) to [How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?](https://stackoverflow.com/q/8030538/3744182) or [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182) or [Json.Net Serialization of Type with Polymorphic Child Object](https://stackoverflow.com/q/29528648/3744182). – dbc Mar 21 '21 at 18:12
  • *..but this code is never hit.* -- then can you [edit] your question to share a [mcve] showing how your register your converter with the framework? We don't even know what framework version you are using. – dbc Mar 21 '21 at 18:14

0 Answers0