反序列化带有抽象或接口成员的类型时会遇到如下错误提示:

Newtonsoft.Json.JsonSerializationException: Could not create an instance of type ITestInterface. Type is an interface or abstract class and cannot be instantiated.

问题和解决办法可以参考:http://stackoverflow.com/questions/15880574/json-net-how-to-deserialize-collection-of-interface-instances

这里总结一下,主要就是自己实现一个继承自SerializationBinder的类,来自己控制命名空间和程序集名称。

例如我们有一个文章类Article,里面有个成员是List<Paragraph>类型来表示段落列表,Paragraph是一个抽象类,其下面有若干个子类,表示诸如文本段落、列表段落、Markdown文本段落、引用段落等等,上述这些类都隶属于一个相同的程序集和命名空间。

另外在另一个程序集中,我还扩展增加了表示文件段落、图像段落的子类。

这样我们的SerializationBinder就这样写:

public class ArticleTypeNameSerializationBinder : SerializationBinder
    {
        public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
        {
            assemblyName = null;
            typeName = serializedType.Name;
        }

        public override Type BindToType(string assemblyName, string typeName)
        {
            //普遍的命名空间和程序集
            var format = "DomainLayer.Entities.{0}, DomainLayer";
            //某些特例
            if (typeName == "FileParagraph" || typeName == "ImageParagraph")
            {
                format = "MyWebSite.Entities.{0}, MyWebSite";
            }
            return Type.GetType(format.FormatWith(typeName), true);
        }
    }

然后序列化时:

var binder = new ArticleTypeNameSerializationBinder();
var jsondata = JsonConvert.SerializeObject(exportdata, Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto,
    Binder = binder
});

反序列化时:

var binder = new ArticleTypeNameSerializationBinder();
var data = JsonConvert.DeserializeObject<Article>(jsondata, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto,
    Binder = binder
});

这样既可实现正确的转换了。

版本信息:

image

转载此文章时须注明转载自”SkyD(斯克迪亚)开发者博客“,并保留此文章的Url链接

作者信息

昵称
斯克迪亚

查看其所发布的所有文章

总积分
2420
注册时间
(2018年5月4日 19:06)

评论

目前还没有任何评论。

[切换到移动版页面]