В JsonSerializerSettings
нет простого параметра, который заставил бы JsonConvert.PopulateObject()
заполнить экземпляр производного типа, как если бы он был экземпляром некоторого базового типа. Чтобы подтвердить это, вы можете проверить источник для JsonSerializerInternalReader.Populate()
, который принимает в качестве аргументов только reader
и target
и извлекает контракт цели непосредственно из его типа:
public void Populate(JsonReader reader, object target)
{
Type objectType = target.GetType();
JsonContract contract = Serializer._contractResolver.ResolveContract(objectType);
Таким образом, ваши опции включают в себя:
Измените определение вашего Element
класса и добавьте [JsonIgnore]
к свойствам, которые вы не хотите заполнять.
Вы, вероятно, не хотите этого делать, потому что это предотвратит сериализацию или десериализацию свойств.
Используйте пользовательский обработчик контрактов , чтобы игнорировать все свойства Element
, которые не являются также свойствами IElementWriter
.
Казалось бы, это лучшее решение.
Предполагая, что вы выберете опцию №2, вы можете ввести следующий пользовательский обработчик контрактов:
public class UpcastingContractResolver<TDerived, TBase> : DefaultContractResolver where TDerived: TBase
{
readonly HashSet<string> baseProperties = ((JsonObjectContract)JsonSerializer.Create().ContractResolver.ResolveContract(typeof(TBase)))
.Properties.Select(p => p.UnderlyingName)
.ToHashSet();
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
if (type == typeof(TDerived) || type.IsSubclassOf(typeof(TDerived)))
{
foreach (var property in properties)
{
if (!baseProperties.Contains(property.UnderlyingName))
property.Ignored = true;
}
}
return properties;
}
}
Затем кэшируйте экземпляр где-нибудь для производительности, как , предложенный Newtonsoft :
static IContractResolver elementAsElementWriterResolver = new UpcastingContractResolver<Element, IElementWriter>();
И напишите ваш element
следующим образом:
// Only populate those properties present in IElementWriter
JsonConvert.PopulateObject(json, element, new JsonSerializerSettings
{
ContractResolver = elementAsElementWriterResolver
});
Демонстрационная скрипка здесь .