最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Serialisingdeserialising class with a abstract base loses value with Newtonsoft and System.Text.Json - Stack Overflow

programmeradmin2浏览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
{
}

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
{
}
Share Improve this question edited Feb 6 at 21:13 marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 6 at 21:08 MalekaiMalekai 4510 bronze badges 4
  • Your code doesn't show any class that implements IServiceableBusPayload. What concrete type do you expect the Payload property to have after deserialization? – StriplingWarrior Commented Feb 6 at 21:39
  • @StriplingWarrior the record inside the TestEvent implements it. TestEventPayload – Malekai Commented Feb 6 at 21:42
  • 1 Should TestEvent extend ServiceableBusEvent<TestEventPayload> then? – StriplingWarrior 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 – Malekai Commented Feb 6 at 21:46
Add a comment  | 

1 Answer 1

Reset to default 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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论