如何将ISerializable对象序列化为SOAP或Json或Xml [英] How to serialize an ISerializable object into SOAP or Json or Xml

查看:104
本文介绍了如何将ISerializable对象序列化为SOAP或Json或Xml的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可ISerializable的复杂对象,我想将其序列化为XML文档(我希望不更改源代码并添加XML序列化属性的东西的节点). ISerializable可与BinaryFormatter配合使用,但是没有标准的方法可以将其序列化为XML或Json. Json.NET库确实支持将ISerializable对象序列化为json,但是该实现存在一个非常小的问题,那就是该类的可序列化的构造方法应该是公共的,以便Json.net检测到它(请参见此问题),这确实使Json.net无法用于我的情况.

I have a complex object which is ISerializable and i want to serialize it into an XML document (node that i rather to not change the source code and add XML serialization attribute stuff). ISerializable works fine with BinaryFormatter, but there is no standard way to serialize it into XML or Json. The Json.NET library does support for serializing a ISerializable object into json, but there is a very small problem with that implementation, and that is the serializable constructor of class should be public in order to Json.net detect it (see this issue) and this does make Json.net unusable for my case.

还有其他方法可以将ISerializable对象序列化/反序列化为xml,Json或任何其他平面文本格式吗?

Is there any other way to serialize/deserialize ISerializable object to/from xml, Json or any other plane text formats?

推荐答案

Json.NET实际上确实支持ISerializable类型的非公开流序列化构造函数.要确认,请参见的源代码DefaultContractResolver.CreateISerializableContract() .

Json.NET does in fact support nonpublic streaming serialization constructors for ISerializable types. For confirmation see the source code for DefaultContractResolver.CreateISerializableContract().

您的实际问题是 ISerializable类型有问题也是集合,而且Json.NET似乎优先于 JsonISerializableContract 用于此类类型,如

Your actual problem is that the ISerializable type in question is also a collection, and it appears Json.NET uses an array contract in preference to a JsonISerializableContract for such types, as shown in DefaultContractResolver.CreateContract():

        if (typeof(IEnumerable).IsAssignableFrom(t))
        {
            return CreateArrayContract(objectType);
        }

        if (CanConvertToString(t))
        {
            return CreateStringContract(objectType);
        }

#if !(DOTNET || PORTABLE40 || PORTABLE)
        if (!IgnoreSerializableInterface && typeof(ISerializable).IsAssignableFrom(t))
        {
            return CreateISerializableContract(objectType);
        }
#endif

要变通解决此问题,您可以创建自己的自定义合同解析器颠倒了这个逻辑:

To work around this problem, you can create your own custom contract resolver that reverses this logic:

public class ISerializableCollectionContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        var contract = base.CreateContract(objectType);
        var underlyingType = Nullable.GetUnderlyingType(objectType) ?? objectType;

        if (!IgnoreSerializableInterface 
            && typeof(ISerializable).IsAssignableFrom(underlyingType)
            && contract is JsonArrayContract
            && !underlyingType.GetCustomAttributes<JsonContainerAttribute>().Any())
        {
            contract = CreateISerializableContract(objectType);
        }

        return contract;
    }
}

您的自定义集合现在应该通过它们的ISerializable接口进行序列化.

Your custom collections should now be serialized through their ISerializable interface.

您可能想要缓存合同解析器以获得最佳性能

这篇关于如何将ISerializable对象序列化为SOAP或Json或Xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆