JSON.NET CustomCreationConverter with nested objec

2019-06-22 14:38发布

that is my very first question I ask on this site, so forgive me if I missed something.

I have some problems deserializing an complex object graph using JSON.NET. My class hierarchy is (simplified) as follows:

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)
    {
    }
}

The classes don't have a default ctor, but a dedicated custom deserialization ctor (beside other public ctor with parameters) as shown in the example. To create an instance I have written an custom creation converter like this:

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;
    }
}

The CreateUsingDesrializationConstructor() extension method looks for the special deserialization ctor and creates an instance using the ctor.

I added to the converter to my JSON.NET serializer instance:

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;
    }
}

When I deserialize an TestBusinessObject I can see from the debugger that the converter is ask for every type whether he is able to create an instance: TestBusinessObject, NestedObject and many other types. But my converter is only requested to create a new TestBusinessObject instance, he is NOT requested to create the nested NestedObject instance what I have expected and what I badly need, since there is some wired logic in the deserialization ctor.

What I'm doing wrong here, how to tell the JsonSerializer to use the converter for every object not even for the root (top level) object?

EDIT: Thinks become more even more complicated when a BusinessObjectBase instance is contained in an object that type I don't know. In this case I also want that the converter is called.

Thanks in advance, Carsten

1条回答
你好瞎i
2楼-- · 2019-06-22 15:23

Try to give [DataContract] attributes to your classes that you want to serialize or deserialize and also make sure whatever data you have in these classes they are also having this attribute. for e.g.

[DataContract]
public class TestBusinessObject : BusinessObjectBase
{
    protected TestBusinessObject(SerializationContext context)
        : base(context)
    {{
    }

    public NestedObject InnerObject { get; set; }
}
查看更多
登录 后发表回答