如何从服务重新序列化数据结构并保持相同的字段名称?
我正在编写一个中间层 WCF 服务,需要从后端 .asmx 服务获取一些数据,然后将其作为 JSON 编码字符串提供给前端。
为此,我向项目中添加对后端服务的引用,使用该引用获取数据,然后使用 DataContractJsonSerializer 重新序列化数据,如下所示:
using (BackendService.BackendServicesSoapClient c = new BackendService.BackendServicesSoapClient())
{
// Get data from back-end
BackendService.SomeData data = c.GetData();
using (MemoryStream msData = new MemoryStream())
{
// Serialise data to a JSON-encoded string
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(BackendService.SomeData));
serializer.WriteObject(msData, data);
jsonEncodedData = System.Text.Encoding.UTF8.GetString(msData.GetBuffer(), 0, Convert.ToInt16(msData.Length));
}
}
现在,总的来说,这是可行的。但是,JSON 编码字符串中的字段名称与原始 SomeData 类中的字段名称不匹配 - 它们都附加了“Field”。
例如,
contents of BackendService.Somedata:
Name : Joe
Age : 33
contents of JSON-encoded string
nameField : Joe
ageField : 33
这似乎与我将服务引用添加到项目时自动生成的代理代码有关。如果我查看生成的引用.cs,我会看到数据类的定义如下:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.225")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.com/Data/BackEnd/2010/11/")]
public partial class SomeData : object, System.ComponentModel.INotifyPropertyChanged {
private string nameField;
private string locationNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
this.RaisePropertyChanged("Name");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public string Age {
get {
return this.ageField;
}
set {
this.ageField = value;
this.RaisePropertyChanged("Age");
}
}
}
与后端服务源中定义的类相比,如下:
public class SomeData
{
public string Name { get; set; }
public string Age { get; set; }
}
有什么方法可以在前端拥有字段名称和后端匹配?
I'm writing a middle-tier WCF service that needs to fetch some data from a back-end .asmx service then serve it up to the front-end as a JSON-encoded string.
I do this by adding a reference to the back-end service to my project, fetching data using that reference, then using a DataContractJsonSerializer to re-serialize the data, like this:
using (BackendService.BackendServicesSoapClient c = new BackendService.BackendServicesSoapClient())
{
// Get data from back-end
BackendService.SomeData data = c.GetData();
using (MemoryStream msData = new MemoryStream())
{
// Serialise data to a JSON-encoded string
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(BackendService.SomeData));
serializer.WriteObject(msData, data);
jsonEncodedData = System.Text.Encoding.UTF8.GetString(msData.GetBuffer(), 0, Convert.ToInt16(msData.Length));
}
}
Now, on the whole this works. However, the field names in the JSON-encoded string don't match those in the oringal SomeData class - they all have "Field" appended.
e.g.
contents of BackendService.Somedata:
Name : Joe
Age : 33
contents of JSON-encoded string
nameField : Joe
ageField : 33
It seems to be something to do with the proxy code that's auto-generated when I add the service reference to my project. If I look in the generated reference.cs I see definitions like this for the data class:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.225")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.com/Data/BackEnd/2010/11/")]
public partial class SomeData : object, System.ComponentModel.INotifyPropertyChanged {
private string nameField;
private string locationNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
this.RaisePropertyChanged("Name");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public string Age {
get {
return this.ageField;
}
set {
this.ageField = value;
this.RaisePropertyChanged("Age");
}
}
}
as compared to the class defined in the back-end service source as:
public class SomeData
{
public string Name { get; set; }
public string Age { get; set; }
}
Is there any way that I can have the field names on the front-end and back-end match?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是您在生成代理时使用 XML Serializer,然后尝试使用 DataContract(Json)Serializer 重新序列化。它们使用不同的属性。您的类没有使用 DataContract 属性进行注释,而是使用 Serialized 属性进行注释。
为此,您需要代理类上的 DataContract 属性,或者需要删除 Serializing 属性。不幸的是,当您使用 XmlSerialier 时,我不确定如何让生成的代码为您执行其中任何一个操作(因为下游服务是 .ASMX 服务)。
为了您自己的理智,创建您自己的类可能是一个好主意,您可以控制该类来创建所需的 JSON,将数据从 ASMX 服务映射到此类,然后使用您的类序列化为 JSON。这样做还有一个额外的好处,即如果 asmx 服务由于某种原因发生更改,它不会影响 JSON,除非您希望它这样做
The problem is that you are using the XML Serializer when generating the proxy and then trying to re-serialize with the DataContract(Json)Serializer. These use different attributes. Your class is not annotated with the DataContract attribute but rather with the Serializable attribute
For this to work you either need the DataContract attribute on the proxy class or you need to remove the Serializable attribute. Unfortunately off the top of my head I'm not sure how you can get the generated code to do either of these for you as you are using the XmlSerialier (because the downstream service is an .ASMX service).
For your own sanity its probably a good idea to create your own class that you control to create the JSON you require, map the data from the ASMX service into this class and then serialize to JSON using your class. This has the added benefit that if the asmx service changed for some reason it wouldn;t affect the JSON unless you wanted it to