c# - 带有嵌套对象的 JSON.NET CustomCreationConverter

标签 c# serialization json.net json-deserialization object-graph

这是我在这个网站上提出的第一个问题,所以如果我遗漏了什么,请原谅我。

我在使用 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)
    {
    }
}

这些类没有默认构造函数,但有一个专用的自定义反序列化构造函数(除了其他带有参数的公共(public)构造函数),如示例所示。为了创建一个实例,我编写了一个自定义创建转换器,如下所示:

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() 扩展方法查找特殊的反序列化构造函数并使用该构造函数创建一个实例。

我将转换器添加到我的 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 时,我可以从调试器中看到转换器询问他是否能够创建实例的每种类型:TestBusinessObject、NestedObject 和许多其他类型。但是我的转换器只被请求创建一个新的 TestBusinessObject 实例,NOT 请求他创建嵌套的 NestedObject 实例,这是我所期望的和我急需的,因为在反序列化 ctor 中有一些有线逻辑.

我在这里做错了什么,如何告诉 JsonSerializer 为每个对象使用转换器,甚至不为根(顶级)对象使用转换器?

编辑: 当 BusinessObjectBase 实例包含在我不知道的类型的对象中时,思考会变得更加复杂。在这种情况下,我还希望调用转换器。

提前致谢, 卡斯滕

最佳答案

尝试为您想要序列化或反序列化的类提供 [DataContract] 属性,并确保您在这些类中拥有的任何数据也具有此属性。例如

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

    public NestedObject InnerObject { get; set; }
}

关于c# - 带有嵌套对象的 JSON.NET CustomCreationConverter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20406717/

相关文章:

c# - 为什么 C# 整数输入不接受正确的值?

c# - writealltextasync 不会将所有文本写入文件

c# - 从 Google 图书下载文件

C#:打印对象的所有属性

c# - 自定义 JSON.Net 输出

c# - 扩展 DefaultContractResolver 以将 ExpandoObject 子属性转换为 PascalCase

c# - 有没有办法在没有 Linq to Entities 的情况下使用 SqlSpatialFunctions?

java - 使用 Play 2 和远程 Akka 集群实现序列化

c++ - 处理从 boost 序列化中删除的变量

c# - 使用 C# 将 XDocument 或 XmlDocument 转换为 JSON