Как повторно сериализовать структуру данных из службы и сохранить те же имена полей? - PullRequest
0 голосов
/ 20 июля 2011

Я пишу сервис 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-кодированной строке не совпадают с именами в классе oringal SomeData - к ним добавлен «Field».

, например

contents of BackendService.Somedata:
    Name  : Joe
    Age   : 33

contents of JSON-encoded string
    nameField : Joe
    ageField : 33

Похоже, что-то связано с прокси-кодом, который генерируется автоматически, когда я добавляю ссылку на сервис в свой проект. Если я посмотрю в сгенерированном reference.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; }
}

Есть ли какой-нибудь способ, которым я могу иметь имена полей во внешнем и внутреннем совпадении?

1 Ответ

1 голос
/ 20 июля 2011

Проблема заключается в том, что вы используете XML Serializer при создании прокси-сервера, а затем пытаетесь повторно сериализовать с помощью DataContract (Json) Serializer.Они используют разные атрибуты.Ваш класс не аннотирован атрибутом DataContract, а скорее атрибутом Serializable

Чтобы это работало, вам нужен либо атрибут DataContract для прокси-класса, либо вам необходимо удалить атрибут Serializable.К сожалению, я не уверен, как вы можете заставить сгенерированный код выполнить любое из этих действий для вас, когда вы используете XmlSerialier (потому что последующий сервис - это сервис .ASMX).

Для вашего же здоровья, вероятно, хорошей идеей будет создание собственного класса, которым вы управляете, для создания требуемого JSON, сопоставления данных из службы ASMX с этим классом, а затем сериализации в JSON с использованием вашего класса.Это дает дополнительное преимущество: если по какой-то причине служба asmx изменилась, это не повлияет на JSON, если вы не захотите

...