Это невозможно с System.Text.Json
дюйм. NET Core 3.1, кроме записи пользовательского JsonConverter
для Notification
. Сериализатор сериализует свойства publi c типа, но свойства интерфейса по умолчанию не реализованы как свойства класса , вместо этого они реализуются через какой-то механизм расширения. См. Spe c: методы интерфейса по умолчанию
Добавить поддержку виртуальных методов расширения - методов в интерфейсах с конкретными реализациями . .
Только когда свойство интерфейса по умолчанию переопределено , свойство экземпляра фактически добавляется к реализующему конкретному типу и, таким образом, становится сериализуемым.
Для подтверждения , если мы изменим классы из вашего 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
Обратите внимание, что просто нет свойства экземпляра или метода, соответствующего SeverityName
в Notification
- но есть в NotificationWithOverride
. При отсутствии свойства для сериализации сериализатор не выводит значение SeverityName
.
Примечания:
System.Text.Json
согласуется с другими сериализаторами в этом отношении; и он, и Json. NET генерируют точно такие же JSON:
{"Severity":0,"Message":"Message"}
для Notification
. {"SeverityName":"info","Severity":0,"Message":"Message"}
для NotificationWithOverride
.
С Json. NET может быть возможно создать настраиваемый преобразователь контрактов , который автоматически добавляет недостающие свойства по умолчанию, но System.Text.Json
не имеет доступа publi c к сопоставителю контрактов; для подтверждения см. вопрос System.Text. Json API есть ли что-то вроде IContractResolver , на который ответ: сейчас нет .
В c# 8.0 невозможно переопределить метод интерфейса по умолчанию в конкретном классе и вызвать метод базового интерфейса. См. Как я могу вызвать метод по умолчанию вместо конкретной реализации , Создание виртуального члена предотвращает вызов реализации интерфейса по умолчанию и вызывает исключение StackOverflowException в C# 8 и Реализации интерфейса по умолчанию и base()
вызывает для получения подробной информации.
Чтобы обойти это, я добавил static
метод интерфейса к INotification
, который инкапсулирует logi c по умолчанию, а затем вызвал его как из метода экземпляра интерфейса по умолчанию, так и из метода класса переопределения.
Демо скрипт, который показывает выше можно найти здесь .