Data Contract Serializer - How to omit the outer element of a collection

泄露秘密 提交于 2019-11-26 07:49:08

问题


How do I serialize a list without the outer element using the Data Contract Serializer? I am using .Net 3.5. I have a class that contains a list, amongst other things, that I wish to serialize without the outer element to be compliant with the pertinent XSD:

[DataContract(Name=\"MyClass\")]
public class MyClass
{
...
[DataMember(Name=\"Parameters\")]
public List<Parameter> Parameters;
...
}

[DataContract(Name=\"Parameter\")]
public struct Parameter
{
    [DataMember(Name=\"ValueName\")]string ValueName;
    [DataMember(Name=\"Value\")]int Value;
    public Parameter(string ValueName, int Value)
    {
        this.ValueName = ValueName;
        this.Value = Value;            
    }
}

The above serializes as (assuming only one Parameter in the list):

<MyClass>
    <Parameters>
       <Parameter>
           <ValueName></ValueName>
           <Value></Value>
       </Parameter>
    </Parameters>
</MyClass>

I would like to serialize it as follows:

<MyClass> 
       <Parameter>
           <ValueName></ValueName>
           <Value></Value>
       </Parameter>
</MyClass>

Using the XmlSerializer I can do this by applying the [XmlElement] to the list:

[XmlElement (\"Parameter\")]
public List<Parameter> Parameters;

However I do not want to use the XmlSerializer because my class has a few properties that are not serialization friendly and I was hoping to deal with those using the [OnSerializing] family of attributes.

Thanks.


回答1:


The DataContract serializer does not allow this degree of control over the resulted XML, you will have to use instead the XmlSerializer in order to achieve this.




回答2:


Use a collection data contract:

    [CollectionDataContract(Name = "MyClass", ItemName = "Parameter")]
    public class ParameterList : List<Parameter>
    {

    }

Here is the actual code:

public class TestSerialize
{
    [DataContract(Name = "Parameter")]
    public struct Parameter
    {
        [DataMember(Name = "ValueName")] string ValueName;
        [DataMember(Name = "Value")] int Value;
        public Parameter(string ValueName, int Value)
        {
            this.ValueName = ValueName;
            this.Value = Value;
        }
    }

    [CollectionDataContract(Name = "MyClass", ItemName = "Parameter")]
    public class ParameterList : List<Parameter>
    {

    }


    public string Serialize(ParameterList plist)
    {
        var serializer = new DataContractSerializer(plist.GetType());
        var output = new StringBuilder();
        var xmlWriter = XmlWriter.Create(output);

        serializer.WriteObject(xmlWriter, plist);
        xmlWriter.Close();

        return output.ToString();
    }


    public void Serialize_produces_2Levels_of_xml()
    {
        ParameterList p = new ParameterList
        {
            new Parameter("First", 1),
            new Parameter("Second", 2),
        };

        var xml = Serialize(p);
    }
}

if you run this you will get the following XML:

<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Serialize.Test">
    <Parameter>
        <Value>1</Value>
        <ValueName>First</ValueName>
    </Parameter>
    <Parameter>
        <Value>2</Value>
        <ValueName>Second</ValueName>
    </Parameter>
</MyClass>



回答3:


The below works using MessageContracts although is a 'hack' - it attributes the "MyClass" element to the List member and excludes the wrapper namespace for "MyClass".

[ServiceContract(Namespace="")]
public interface IService1
{
    [OperationContract]
    MyClass GetParameters();
    // TODO: Add your service operations here
}

[DataContract(Namespace="")]
public class Parameter
{
    [DataMember]
    public string ValueName
    {
        get;
        set;
    }
    [DataMember]
    public int Value
    {
        get;
        set;
    }

    public Parameter(string ValueName, int Value) 
    { 
        this.ValueName = ValueName; 
        this.Value = Value; 
    } 
}

[MessageContract(IsWrapped = false, WrapperNamespace="")]
public class MyClass
{
    [MessageBodyMember(Name = "MyClass", Namespace = "")]
    public List<Parameter> Parameters
    {
        get;
        set;
    }
}


来源:https://stackoverflow.com/questions/8591045/data-contract-serializer-how-to-omit-the-outer-element-of-a-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!