Это мой первый вопрос, который я задаю на этом сайте, так что простите меня, если я что-то пропустил.JSON.NET CustomCreationConverter с вложенными объектами
У меня есть некоторые проблемы десериализации сложного графа объектов с использованием JSON.NET. Мой класс иерархии (упрощенно) следующим образом:
public abstract class BusinessObjectBase
{
protected BusinessObjectBase(SerializationContext context)
{
}
}
public class TestBusinessObject : BusinessObjectBase
{
protected TestBusinessObject(SerializationContext context)
: base(context)
{
}
public NestedObject InnerObject { get; set; }
}
public class NestedObject : BusinessObjectBase
{
protected NestedObject(SerializationContext context)
: base(context)
{
}
}
классы не имеют CTOR по умолчанию, но специальный заказ десериализации CTOR (рядом с другим общественным CTOR с параметрами), как показано в примере. Чтобы создать экземпляр я написал конвертер обычай создания так:
internal class BusinessObjectCreationConverter : CustomCreationConverter<BusinessObjectBase>
{
public override bool CanConvert(Type objectType)
{
return typeof(BusinessObjectBase).IsAssignableFrom(objectType) && !objectType.IsAbstract;
}
public override BusinessObjectBase Create(Type objectType)
{
var businessObject = objectType.CreateUsingDesrializationConstructor<BusinessObjectBase>();
return businessObject;
}
}
Метод расширения CreateUsingDesrializationConstructor() ищет специального десериализации CTOR и создает экземпляр с помощью CTOR.
Я добавил к преобразователю моего Json.NET сериализатора Например:
public class NewtonsoftJsonSerializer : ISerializer
{
public NewtonsoftJsonSerializer()
: this(new JsonSerializer
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
DefaultValueHandling = DefaultValueHandling.Ignore,
ContractResolver = new KsJsonContractResolver()
})
{
this.serializer.Converters.Add(new BusinessObjectCreationConverter());
}
public T Deserialize<T>(Stream stream)
{
T result;
using (var streamReader = new StreamReader(stream, Encoding.UTF8, true, BufferSize, true))
using (var jsonReader = new JsonTextReader(streamReader))
{
result = this.serializer.Deserialize<T>(jsonReader);
}
return result;
}
}
Когда я десериализация TestBusinessObject я могу видеть из отладчика, что преобразователь задать для каждого типа, является ли он в состоянии создать instance: TestBusinessObject, NestedObject и многие другие типы. Но моему конвертеру требуется только создать новый экземпляр TestBusinessObject, он NOT попросил создать вложенный экземпляр NestedObject, что я ожидал, и что мне очень нужно, поскольку в десериализации ctor есть некоторая проводная логика.
Что я здесь делаю неправильно, как сказать JsonSerializer использовать конвертер для каждого объекта даже для объекта root (верхнего уровня)?
EDIT: Думает становится более еще более сложным, когда экземпляр BusinessObjectBase содержится в объекте, что печатает я не знаю. В этом случае я также хочу, чтобы конвертер был вызван.
Спасибо заранее, Карстен
Можете ли вы прояснить реальный быстро; вы создаете только объект внешнего уровня и хотите также вложенные объекты, или вы создаете объект внешнего уровня плюс вложенные и только хотите объект внешнего уровня? Я думаю, что вы сможете решить эту проблему без использования пользовательского сериализатора в зависимости от вашего ответа. – evanmcdonnal
Конвертер создает только внешний объект уровня. Я хочу, чтобы объект внутреннего уровня создавался вторым вызовом конвертера. – CGR
Я забыл упомянуть еще одну ситуацию: объект BusinessObjectBase может быть внутренним объектом non BusinessObjectBase. В этом случае, конечно же, должен быть вызван конвертер создания. – CGR