64

在 C# 中,如何让 XmlSerializer 在序列化期间忽略属性,但在反序列化期间不忽略?(或者我如何对 Json.net 做同样的事情?)

为了防止属性被序列化,您可以添加XmlIgnore属性:

[XmlIgnore]
public int FooBar {get;set;}

这将导致<FooBar>在序列化过程中省略标签。

但是,这也意味着<FooBar>在反序列化过程中将忽略标签。

就我而言,我在请求中接受来自用户的一组项目,如果用户想要添加、修改或删除项目,则可以为每个项目指定一个操作属性。我想对 GET 列表调用使用相同的模型对象,并且不想返回此操作属性。我希望这将是一个很常见的情况。

另一个用例:假设你有一个圆形对象

public class Circle
{
    public double Radius { get; set; }
}

然后你修改它以添加一个直径属性

public class Circle2
{
    public double Diameter { get; set; }
    public double Radius { get { return Diameter / 2; } set { Diameter = value*2; } }
}

您可能只想序列化直径,但仍然能够反序列化仅包含半径的旧格式的 xml 文件。

我做了我的研究,没有发现任何东西,因此这个问题

解决方案:我想出了解决方案。我可以在此 MSDN 文档中添加一个始终返回 false 的 ShouldSerialize 属性,详细信息

(如果重新打开此问题,则可以将此解决方案添加为实际答案)

4

2 回答 2

46

这是 Manoj 概述的解决方案:

如果你想抑制特定属性的序列化Foo,但仍然能够反序列化它,你可以添加一个public bool ShouldSerializeFoo()总是返回 false 的方法。

例子:

public class Circle2
{
    public double Diameter { get; set; }
    public double Radius { get { return Diameter / 2; } set { Diameter = value*2; } }

    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public bool ShouldSerializeRadius() {return false;}
}

这将导致 Radius 不被序列化,但仍然允许它被反序列化。

此方法必须是公共的,XMLSerializer 才能找到它,因此为了避免污染命名空间,您可以添加EditorBrowsable属性以将其隐藏在 IDE 中。不幸的是,这种隐藏仅在当前项目中将程序集作为 DLL 引用时才有效,但如果您使用此代码编辑实际项目则无效。

于 2014-03-05T11:25:14.830 回答
43

如果要在使用 XmlSerializer 进行序列化时忽略元素,可以使用 XmlAttributeOverrides:

XmlAttributeOverrides overrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
attribs.XmlIgnore = true;
attribs.XmlElements.Add(new XmlElementAttribute("YourElementName"));
overrides.Add(typeof(YourClass), "YourElementName", attribs);

XmlSerializer ser = new XmlSerializer(typeof(YourClass), overrides);
ser.Serialize(...
于 2013-08-14T21:21:46.477 回答