这对于 .NET Core 3.1 中的 System.Text.Json 是不可能的,除非为 Notification 编写自定义 JsonConverter。序列化器序列化类型的公共属性,但默认接口属性不作为类属性实现,而是通过某种扩展机制实现。请参阅规范:default interface methods
添加对虚拟扩展方法的支持 - 具有具体实现的接口中的方法。 .
只有当默认接口属性被覆盖时,实例属性才会真正添加到实现的具体类型中,从而变成可序列化的。
为了确认,如果我们修改您的fiddle 中的类如下:
public interface INotification
{
Severity Severity { get; set; }
string Message { get; set; }
static string MakeDefaultSeverityName<TNotification>(TNotification notification) where TNotification : INotification => notification?.Severity.ToString().ToLower();
public string SeverityName => MakeDefaultSeverityName(this);
}
public class Notification : INotification
{
public Severity Severity { get; set; }
public string Message { get; set; }
}
public class NotificationWithOverride : Notification
{
public string SeverityName => INotification.MakeDefaultSeverityName(this);
}
并使用反射打印出这两种类型的属性和方法:
Console.WriteLine("Properties of {0}: {1}", typeof(TNotification).Name, string.Join(", ", typeof(TNotification).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name)));
Console.WriteLine("Methods of {0}: {1}", typeof(TNotification).Name, string.Join(", ", typeof(TNotification).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(p => p.Name)));
对于Notification,我们得到以下结果:
Properties of Notification: Severity, Message
Methods of Notification: get_Severity, set_Severity, get_Message, set_Message, GetType, MemberwiseClone, Finalize, ToString, Equals, GetHashCode
对于NotificationWithOverride:
Properties of NotificationWithOverride: SeverityName, Severity, Message
Methods of NotificationWithOverride: get_SeverityName, get_Severity, set_Severity, get_Message, set_Message, GetType, MemberwiseClone, Finalize, ToString, Equals, GetHashCode
请注意,在Notification 中没有对应于SeverityName 的实例属性或方法——但在NotificationWithOverride 中有。由于缺少要序列化的属性,序列化程序不会输出 SeverityName 值。
注意事项:
-
System.Text.Json在这方面与其他序列化器一致;它和 Json.NET 都生成完全相同的 JSON:
-
{"Severity":0,"Message":"Message"} 为Notification。
-
{"SeverityName":"info","Severity":0,"Message":"Message"} 为NotificationWithOverride。
1234563如需确认,请参阅问题 System.Text.Json API is there something like IContractResolver 的答案,目前没有。
-
在 c# 8.0 中,无法覆盖具体类中的默认接口方法并调用基接口方法。有关详细信息,请参阅 How can I call the default method instead of the concrete implementation、Making member virtual prevents calling default interface implementation and causes StackOverflowException in C# 8 和 Default interface implementations and base() calls。
为了解决这个问题,我向 INotification 添加了一个 static 接口方法,它封装了默认逻辑,然后从默认接口实例方法和覆盖类方法中调用它。 p>
可以在here找到一个演示小提琴。