【问题标题】:How to not serialize an object based on a property's value?如何不根据属性的值序列化对象?
【发布时间】:2015-06-24 09:27:42
【问题描述】:

如果标签没有泄露,我正在使用 C# 的 XmlSerializer 类。

例如,假设我有一个 Person 类,它具有各种属性,包括年龄 (int)、姓名 (字符串) 和已故 (布尔)。有没有办法指定我不想序列化任何已故标志为真的对象?

编辑:我应该指定,但不幸的是,由于这种情况我无法真正编辑我的对象列表,因为它是另一个类的成员,而这正是我正在序列化的。还有其他建议吗?

【问题讨论】:

  • 所以你有Person对象的枚举?为什么不先过滤掉你不想要的对象呢?
  • 我认为这种逻辑最好放在序列化类中。您应该在序列化之前过滤您的列表或数组。
  • @DavidG 我有一个 Persons 列表作为我正在序列化的另一个类的属性,所以由于情况的性质,我真的不能轻松地从列表中删除东西.
  • 这些对象(Person)列表是否是另一个正在序列化的类的一部分?在这种情况下,我有一个解决方案。
  • @vendettamit 是的。例如,我有一个名为 Beings 的类,其中包含一个 Animals 列表和一个 Persons 列表。我正在序列化众生,而人物也因此被序列化。但是我需要在序列化过程中从该列表中过滤掉某些人。

标签: c# xml serialization


【解决方案1】:

假设您有以下类型的类结构(正如您在评论中指定的)

public class Person 
{
    public int Age { get; set; }

    public string Name { get; set; }

    public bool Deceased { get; set; }
}

public class Being
{
    public string Data { get; set; }

    [XmlElement("Human")]
    public Person Human { get; set; }

    public bool ShouldSerializeHuman()
    {
        return !this.Human.Deceased;
    }
}

在这里我添加了一个名为ShouldSerialize 的方法,这称为XML 序列化模式。在这里,您可以使用XmlArrayXmlArrayItem 用于列表等(使用给定名称)然后ShouldSerialize 检查它是否可以序列化。

以下是我用于测试的代码。

    private static void Main(string[] args)
    {
        var livingHuman = new Person() { Age = 1, Name = "John Doe", Deceased = true };
        var deadHuman = new Person() { Age = 1, Name = "John Doe", Deceased = false };

        XmlSerializer serializer = new XmlSerializer(typeof(Being));

        serializer.Serialize(Console.Out, new Being { Human = livingHuman, Data = "new" });

        serializer.Serialize(Console.Out, new Being { Human = deadHuman, Data = "old" });
    }

这是输出:

==============================

更新:

如果您有作为人类的人的列表:

public class Being
{
    // [XmlAttribute]
    public string Data { get; set; }

    // Here add the following attributes to the property
    [XmlArray("Humans")]
    [XmlArrayItem("Human")]
    public List<Person> Humans { get; set; }

    public bool ShouldSerializeHumans()
    {
        this.Humans = this.Humans.Where(x => !x.Deceased).ToList();
        return true;
    }
}

样本测试:

    private static void Main(string[] args)
    {
        var livingHuman = new Person() { Age = 1, Name = "John Doe", Deceased = true };
        var deadHuman = new Person() { Age = 1, Name = "John Doe", Deceased = false };

        var humans = new List<Person> { livingHuman, deadHuman };
        XmlSerializer serializer = new XmlSerializer(typeof(Being));

        serializer.Serialize(Console.Out, new Being() { Humans = humans, Data = "some other data" });
    }

输出:

【讨论】:

  • 问题在于 Human(s) 是 List,而不是单个对象。有没有办法让 ShouldSerialize 为列表中的单个项目工作?
  • 我喜欢这种方法,但我对它的工作原理感到困惑。序列化器会在过滤值之前克隆对象吗?
  • 此方法(ShouldSerialize propertyName )是在属性被序列化之前重置或发出默认值的可选方法。见documentation。在这里,我欺骗了对值应用过滤器的方法。
【解决方案2】:

如果您有一个Person 对象列表并且只想序列化其中的一些对象,那么只需过滤掉您不需要的对象。例如:

List<Person> people = GetPeople(); //from somewhere
List<Person> filteredPeople = people.Where(p => !p.Deceased);

现在你只需要序列化filteredPeople

【讨论】:

  • 不幸的是,由于我的情况,我不能真正做到这一点。原因见我上面的编辑。
  • 你能把数据复制到另一个对象中吗?
  • 我想我可以创建包含类的其他成员并设置几个 ShouldSerialize 方法来确定我应该序列化哪个方法。明天我得试试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 2019-03-09
  • 1970-01-01
  • 2012-12-31
相关资源
最近更新 更多