What options are there for serialization when returning instances of custom classes from a WebService?
在从web服务返回自定义类实例时,有哪些序列化选项?
We have some classes with a number of child collection class properties as well as other properties that may or may not be set depending on usage. These objects are returned from an ASP.NET .asmx WebService decorated with the ScriptService attribute, so are serialized via JSON serialization when returned by the various WebMethods.
我们有一些类具有一些子类属性以及其他属性,这些属性可能或可能不依赖于使用。这些对象是从ASP返回的。使用ScriptService属性修饰的asmx WebService,通过各种web方法返回时,通过JSON序列化进行序列化。
The problem is that the out of the box serialization returns all public properties, regardless of whether or not they are used, as well as returning class name and other information in a more verbose manner than would be desired if you wanted to limit the amount of traffic.
问题是,开箱即用序列化返回所有公共属性,而不管它们是否被使用,以及以比希望限制通信量更详细的方式返回类名和其他信息。
Currently, for the classes being returned we have added custom javascript converters that handle the JSON serializtion, and added them to the web.config as below:
目前,对于正在返回的类,我们添加了处理JSON序列化的自定义javascript转换器,并将它们添加到web。配置如下:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="CustomClassConverter" type="Namespace.CustomClassConverter" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
But this requires a custom converter for each class. Is there any other way to change the out of the box JSON serialization, either through extending the service, creating a custom serializer or the like?
但是这需要每个类都有一个自定义转换器。是否有其他方法可以通过扩展服务、创建自定义序列化器或类似方法来更改开箱即用的JSON序列化?
Follow Up
@marxidad:
跟进@marxidad:
We are using the DataContractJsonSerializer class in other applications, however I have been unable to figure out how to apply it to these services. Here's an example of how the services are set-up:
我们在其他应用程序中使用DataContractJsonSerializer类,但是我一直无法弄清楚如何将它应用到这些服务中。以下是如何设置服务的示例:
[ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public CustomClass GetCustomClassMethod
{
return new customClass();
}
}
The WebMethods are called by javascript and return data serialized in JSON. The only method we have been able to change the serialization is to use the javascript converters as referenced above?
WebMethods由javascript调用并返回JSON中序列化的数据。我们唯一能够改变序列化的方法是使用上面提到的javascript转换器?
Is there a way to tell the WebService to use a custom DataContractJsonSerializer? Whether it be by web.config configuration, decorating the service with attributes, etc.?
有什么方法可以告诉WebService使用自定义的DataContractJsonSerializer吗?不管是通过网络。配置配置,用属性装饰服务等等?
Update
Well, we couldn't find any way to switch the out of the box JavaScriptSerializer except for creating individual JavaScriptConverters as above.
更新得很好,除了创建单独的javascript转换器之外,我们找不到任何方法来切换javascript序列化器。
What we did on that end to prevent having to create a separate converter was create a generic JavaScriptConverter. We added an empty interface to the classes we wanted handled and the SupportedTypes which is called on web-service start-up uses reflection to find any types that implement the interface kind of like this:
我们在那一端所做的是避免创建一个单独的转换器,那就是创建一个通用的JavaScriptConverter。我们为我们想要处理的类添加了一个空接口,web服务启动时调用的支持类型使用反射找到实现接口的任何类型,类似如下:
public override IEnumerable<Type> SupportedTypes
{
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;
}
}
}
}
}
}
The actual implementation is a bit different so that the type are cached, and we will likely refactor it to use custom attributes rather than an empty interface.
实际的实现有点不同,所以类型被缓存,我们可能会重构它来使用自定义属性,而不是一个空接口。
However with this, we ran into a slightly different problem when dealing with custom collections. These typically just extend a generic list, but the custom classes are used instead of the List<> itself because there is generally custom logic, sorting etc. in the collection classes.
但是,在处理自定义集合时,我们遇到了一个稍微不同的问题。这些通常只是扩展一个泛型列表,但是使用自定义类而不是列表<>本身,因为集合类中通常有自定义逻辑、排序等。
The problem is that the Serialize method for a JavaScriptConverter returns a dictionary which is serialized into JSON as name value pairs with the associated type, whereas a list is returned as an array. So the collection classes could not be easily serialized using the converter. The solution for this was to just not include those types in the converter's SupportedTypes and they serialize perfectly as lists.
问题是,JavaScriptConverter的序列化方法返回一个字典,它被序列化为JSON,作为与关联类型的名称值对,而列表作为数组返回。因此,无法使用转换器轻松序列化集合类。解决这个问题的方法是不将这些类型包含在转换器的支持类型中,它们可以作为列表进行完美的序列化。
So, serialization works, but when you try to pass these objects the other way as a parameter for a web service call, the deserialization breaks, because they can't be the input is treated as a list of string/object dictionaries, which can't be converted to a list of whatever custom class the collection contains. The only way we could find to deal with this is to create a generic class that is a list of string/object dictionaries which then converts the list to the appropriate custom collection class, and then changing any web service parameters to use the generic class instead.
序列化工作,但是当你试图通过这些对象作为参数的web服务调用,反序列化休息,因为他们不能输入被视为字符串/对象字典的列表,它不能被转化为一个列表集合包含的任何自定义类。我们可以找到的解决这个问题的唯一方法是创建一个泛型类,它是一个字符串/对象字典列表,然后将列表转换为适当的自定义集合类,然后更改任何web服务参数以使用泛型类。
I'm sure there are tons of issues and violations of "best practices" here, but it gets the job done for us without creating a ton of custom converter classes.
我确信这里有大量的问题和违反“最佳实践”的行为,但是它可以为我们完成任务,而无需创建大量的自定义转换器类。
2
If you don't use code-generated classes, you can decorate your properties with the ScriptIgnoreAttribute to tell the serializer to ignore certain properties. Xml serialization has a similar attribute.
如果不使用代码生成的类,可以使用ScriptIgnoreAttribute修饰属性,以告诉序列化器忽略某些属性。Xml序列化具有类似的属性。
Of course, you cannot use this approach if you want to return some properties of a class on one service method call and different properties of the same class on a different service method call. If you want to do that, return an anonymous type in the service method.
当然,如果您希望在一个服务方法调用上返回类的某些属性,以及在不同的服务方法调用上返回相同类的不同属性,则不能使用这种方法。如果要这样做,请在服务方法中返回一个匿名类型。
[WebMethod]
[ScriptMethod]
public object GimmieData()
{
var dalEntity = dal.GimmieEntity(); //However yours works...
return new
{
id = dalEntity.Id,
description = dalEntity.Desc
};
}
The serializer could care less about the type of the object you send to it, since it just turns it into text anyway.
序列化器不太关心发送给它的对象的类型,因为它只是将它转换为文本。
I also believe that you could implement ISerializable on your data entity (as a partial class if you have code-gen'd data entities) to gain fine-grained control over the serialization process, but I haven't tried it.
我还相信,您可以在您的数据实体上实现iserizable(如果您有代码生成的数据实体,它是一个局部类),以获得对序列化过程的细粒度控制,但我还没有尝试过。
2
I know this thread has been quiet for a while, but I thought I'd offer that if you override the SupportedTypes property of JavaScriptConverter in you custom converter, you can add the types that should use the converter. This could go into a config file if necessary. That way you wouldn't need a custom converter for each class.
我知道这个线程已经沉寂了一段时间,但是我认为如果您在自定义转换器中覆盖了JavaScriptConverter的SupportedTypes属性,您可以添加应该使用转换器的类型。如果需要,可以将其放入配置文件中。这样,您就不需要为每个类使用自定义转换器。
I tried to create a generic converter but couldn't figure out how to identify it in the web.config. Would love to find out if anyone else has managed it.
我尝试创建一个通用的转换器,但是无法在web.config中识别它。我很想知道是否有人管理过它。
I got the idea when trying to solve the above issue and stumbled on Nick Berardi's "Creating a more accurate JSON .NET Serializer" (google it).
我在尝试解决上述问题时想到了这个主意,并偶然发现Nick Berardi的“创建更精确的JSON . net序列化器”(谷歌it)。
Worked for me:)
为我工作)
Thanks to all.
感谢所有。
1
If you're using .NET 3.x (or can), a WCF service is going to be your best bet.
如果你正在使用。net 3。x(或可以),WCF服务将是你最好的选择。
You can selectively control which properties are serialized to the client with the [DataMember] attribute. WCF also allows more fine-grained control over the JSON serialization and deserialization, if you desire it.
您可以有选择地控制哪些属性被使用[DataMember]属性序列化到客户端。如果您愿意,WCF还允许对JSON序列化和反序列化进行更细粒度的控制。
This is a good example to get started: http://blogs.msdn.com/kaevans/archive/2007/09/04/using-wcf-json-linq-and-ajax-passing-complex-types-to-wcf-services-with-json-encoding.aspx
这是一个很好的例子:http://blogs.msdn.com/kaevans/archive/2007/09/09/04/usingwcf -json- linqand -wcf- - -wcf- wcf- serviceswith-json -encoding.aspx。
0
You can use the System.Runtime.Serialization.Json.
DataContractJsonSerializer
class in the System.ServiceModel.Web.dll
assembly.
您可以使用system . runtime. serializ.json。System.ServiceModel.Web中的DataContractJsonSerializer类。dll组装。
0
Don't quote me on this working for certain, but I believe this is what you are looking for.
不要肯定地引用我的话,但我相信这就是你要找的。
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public XmlDocument GetXmlDocument()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(_xmlString);
return xmlDoc;
}
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2008/10/01/c1fdf7ce784c40c47f45b88afc2f56f9.html。