从WebService返回自定义类的实例时,有哪些序列化选项?
我们有一些具有许多子集合类属性的类以及根据用途可能设置也可能不设置的其他属性.这些对象是从装有ScriptService属性的ASP.NET .asmx WebService返回的,因此在各种WebMethods返回时通过JSON序列化进行序列化.
问题是开箱即用的序列化会返回所有公共属性,无论它们是否被使用,以及以比您想要限制的数量更加详细的方式返回类名和其他信息.交通.
目前,对于返回的类,我们添加了处理JSON序列化的自定义javascript转换器,并将它们添加到web.config中,如下所示:
但这需要每个类的自定义转换器.有没有其他方法可以通过扩展服务,创建自定义序列化器等来改变开箱即用的JSON序列化?
跟进
@marxidad:
我们在其他应用程序中使用DataContractJsonSerializer类,但是我无法弄清楚如何将它应用于这些服务.以下是如何设置服务的示例:
[ScriptService] public class MyService : System.Web.Services.WebService { [WebMethod] public CustomClass GetCustomClassMethod { return new customClass(); } }
WebMethods由javascript调用,并返回以JSON序列化的数据.我们能够更改序列化的唯一方法是使用上面引用的javascript转换器?
有没有办法告诉WebService使用自定义DataContractJsonSerializer?是否通过web.config配置,使用属性装饰服务等?
更新
嗯,我们找不到任何方法来切换开箱即用的JavaScriptSerializer,除了如上所述创建单独的JavaScriptConverters.
为此我们为防止必须创建单独的转换器而做的是创建一个通用的JavaScriptConverter.我们为我们想要处理的类添加了一个空接口,在web-service启动时调用的SupportedTypes使用反射来查找实现接口的任何类型,如下所示:
public override IEnumerableSupportedTypes { get { foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { AssemblyBuilder dynamicAssemblyCheck = assembly as AssemblyBuilder; if (dynamicAssemblyCheck == null) { foreach (Type type in assembly.GetExportedTypes()) { if (typeof(ICustomClass).IsAssignableFrom(type)) { yield return type; } } } } } }
实际的实现有点不同,因此类型被缓存,我们可能会重构它以使用自定义属性而不是空接口.
但是,在处理自定义集合时,我们遇到了一个稍微不同的问题.这些通常只是扩展一个通用列表,但是使用自定义类而不是List <>本身,因为在集合类中通常有自定义逻辑,排序等.
问题是JavaScriptConverter的Serialize方法返回一个字典,该字典序列化为JSON,作为具有关联类型的名称值对,而列表作为数组返回.因此,使用转换器无法轻松序列化集合类.解决方案是在转换器的SupportedTypes中不包含这些类型,并将它们完美地序列化为列表.
因此,序列化可行,但是当您尝试以另一种方式传递这些对象作为Web服务调用的参数时,反序列化会中断,因为它们不能将输入视为字符串/对象字典列表,这可以不能转换为集合包含的任何自定义类的列表.我们可以找到解决这个问题的唯一方法是创建一个泛型类,它是一个字符串/对象字典列表,然后将列表转换为适当的自定义集合类,然后更改任何Web服务参数以使用泛型类.
我确信这里存在大量问题和违反"最佳实践"的行为,但它可以为我们完成工作,而无需创建大量的自定义转换器类.