Избегайте использования пространства имен "http://www.w3.org/2001/XMLSchema-instance" с.Net DataContractSerializer
У меня есть серия классов, которые я конвертирую в XML с помощью.NET DataContractSerializer в.NET 4.0. Сериализация работает нормально, и я могу без труда разобрать XML и заново создать объекты.NET.
Однако большинство DataMember не являются обязательными. DataMember(IsRequired = false). Это прекрасно работает при десериализации XML, когда вы можете просто пропустить узел XML из документа, но при сериализации существующего объекта в XML DataContractSerializer настаивает на выписывании свойств, которые имеют нулевые значения в виде узлов с атрибутом, например
[DataContract(Name = "response", Namespace = "http://domain.com/name")]
public class MyResponseClass
{
[DataMember(Name = "count", IsRequired = true, Order = 0)]
public int Count { get; set; }
[DataMember(Name = "info", IsRequired = false, Order = 1)]
public InfoClass Info { get; set; }
[DataMember(Name = "metadata", IsRequired = false, Order = 2)]
public MetadataList Metadatas { get; set; }
}
можно сериализовать из
<response xmlns="http://domain.com/name">
<count>4</count>
</response>
Однако, если я сериализую объект, он создает:
<response xmlns="http://domain.com/name" xmlns:i="http://www.w3.org/2001/XmlSchema-instance">
<count>4</count>
<info i:nil="true" />
<metadata i:nil="true" />
</response>
Есть ли способ заставить DataContractSerializer не записывать узел вместо этого, когда он имеет нулевое значение?
2 ответа
Использование EmitDefaultValue = false
чтобы пропустить значения по умолчанию в XML:
[DataContract(Name = "response", Namespace = "http://domain.com/name")]
public class MyResponseClass
{
[DataMember(Name = "count", IsRequired = true, Order = 0, EmitDefaultValue = false)]
public int Count { get; set; }
[DataMember(Name = "info", IsRequired = false, Order = 1, EmitDefaultValue = false)]
public InfoClass Info { get; set; }
[DataMember(Name = "metadata", IsRequired = false, Order = 2, EmitDefaultValue = false)]
public MetadataList Metadatas { get; set; }
}
удалять xmlns:i="http://www.w3.org/2001/XmlSchema-instance"
вы должны использовать, например, Replace()
как в следующем примере
public void Write(string filePath, MyResponseClass myResponse)
{
var serializer = new DataContractSerializer(typeof(MyResponseClass));
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
using (var xmlWriter = XmlWriter.Create(writer))
{
serializer.WriteObject(xmlWriter, myResponse);
}
using (StreamWriter stream = new StreamWriter(filePath))
{
sb = sb.Replace(" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
stream.Write(sb);
}
}
с уважением:)
(Я отправил этот ответ случайно в неправильном вопросе, но я думаю, что он также полезен здесь, поэтому я не удаляю его сейчас)
[DataContract(Namespace = "")]
на вершине каждого класса делает это намного лучше. Он удаляет пространства имен datacontract и префиксы уродливых узлов. Однако стандартное пространство имен остается. Это было нормально для моего случая.
До:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/MyClassname">
<prop1>true</prop1>
<prop2 xmlns:d2p1="http://schemas.datacontract.org/2004/07/MySubclassname">
<d2p1:sub>true</d2p1:sub>
</prop2>
</root>
После:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<prop1>true</prop1>
<prop2>
<sub>true</sub>
</prop2>
</root>