问题
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