0

I'm trying to serialise and deserialise a servicebus event class, my event inherits from an abstract base with a generic parameter for the payload, and my base class implements an interface.

No matter what options I have tried in both Newtonsoft and System.Text.Json, I cannot get this working. The serialise doesn't serialise the inner payload, and the deserialise throws this error:

private async Task ProcessMessageAsync<T>(ProcessMessageEventArgs args)
{
    try
    {
        var eventTypeInstance = typeof(T);

        var options = new JsonSerializerSettings(){
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new List<Newtonsoft.Json.JsonConverter> { new StringEnumConverter() }
        };

        var body = Encoding.UTF8.GetString(args.Message.Body.ToArray());

        if (eventTypeInstance != null)
        {
            var eventInstance = JsonConvert.DeserializeObject(body, typeof(T), options);
        }
    }
}

Newtonsoft.Json.JsonSerializationException: 'Could not create an instance of type ServiceableBus.IServiceableBusPayload. Type is an interface or abstract class and cannot be instantiated. Path 'payload.field1', line 5, position 17.'

<T> is my concrete type.

Below are my class definitions:

public class TestEvent : ServiceableBusEvent<IServiceableBusPayload>
{
    public const string Topic = "test-event";

    public record TestEventPayload(string Field1, int Field2, int Field3) : IServiceableBusPayload;
}

public abstract class ServiceableBusEvent<T> : IServiceableBusEvent where T : IServiceableBusPayload
{
    [JsonPropertyName("messageTypeName")]
    public string MessageTypeName { get; set; }

    [JsonPropertyName("createdAt")]
    public DateTime CreatedAt { get; set; }

    [JsonPropertyName("payload")]
    public T Payload { get; set; }
}

public interface IServiceableBusEvent
{
}

public interface IServiceableBusPayload
{
}
4
  • Your code doesn't show any class that implements IServiceableBusPayload. What concrete type do you expect the Payload property to have after deserialization? Commented Feb 6 at 21:39
  • @StriplingWarrior the record inside the TestEvent implements it. TestEventPayload Commented Feb 6 at 21:42
  • 1
    Should TestEvent extend ServiceableBusEvent<TestEventPayload> then? Commented Feb 6 at 21:42
  • @StriplingWarrior you sir are a genius.... that has worked. If you want to post the answer I will mark it as correct Commented Feb 6 at 21:46

1 Answer 1

2

Since TestEvent extends ServiceableBusEvent<IServiceableBusPayload>, the type of the Payload property is IServiceableBusPayload, so the deserializer has no way to know which concrete type you want.

Make TestEvent extend ServiceableBusEvent<TestEventPayload> so it knows to use that specific type for the Payload property.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.