Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent a datamember from being serialized

I only want only to de-serializing a certain data member, without serializing it.

I understand I can set EmitDefaultValue =false, and set the value to null.

But I also do not want to change the value of the datamember, is there any other way of achieving this?

The serializer is DataContractSerializer. :)

Thanks.

like image 634
RKM Avatar asked Nov 04 '11 14:11

RKM


Video Answer


3 Answers

You can change the value of the data member before the serialization (to the default value, so it doesn't get serialized), but then after the serialization you'd change it back - using the [OnSerializing] and [OnSerialized] callbacks (more information in this blog post). This works fine as long as you don't have multiple threads serializing the object at the same time.

public class StackOverflow_8010677
{
    [DataContract(Name = "Person", Namespace = "")]
    public class Person
    {
        [DataMember]
        public string Name;
        [DataMember(EmitDefaultValue = false)]
        public int Age;

        private int ageSaved;
        [OnSerializing]
        void OnSerializing(StreamingContext context)
        {
            this.ageSaved = this.Age;
            this.Age = default(int); // will not be serialized
        }
        [OnSerialized]
        void OnSerialized(StreamingContext context)
        {
            this.Age = this.ageSaved;
        }

        public override string ToString()
        {
            return string.Format("Person[Name={0},Age={1}]", this.Name, this.Age);
        }
    }

    public static void Test()
    {
        Person p1 = new Person { Name = "Jane Roe", Age = 23 };
        MemoryStream ms = new MemoryStream();
        DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
        Console.WriteLine("Serializing: {0}", p1);
        dcs.WriteObject(ms, p1);
        Console.WriteLine("   ==> {0}", Encoding.UTF8.GetString(ms.ToArray()));
        Console.WriteLine("   ==> After serialization: {0}", p1);
        Console.WriteLine();
        Console.WriteLine("Deserializing a XML which contains the Age member");
        const string XML = "<Person><Age>33</Age><Name>John Doe</Name></Person>";
        Person p2 = (Person)dcs.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(XML)));
        Console.WriteLine("  ==> {0}", p2);
    }
}
like image 51
carlosfigueira Avatar answered Sep 30 '22 01:09

carlosfigueira


Which serializer?If this is XmlSerializer then either:

public int Foo {get;set;}
[XmlIgnore]
public bool FooSpecified {
    get { return false; } // never serialize
    set { }
}

or

public int Foo {get;set;}
public bool ShouldSerializeFoo() { return false; }

will do this. A quick test shows that this doesn't work for DataContractSerializer, though. protobuf-net also supports both of these, for info.

like image 32
Marc Gravell Avatar answered Sep 30 '22 01:09

Marc Gravell


Have you tried decorating the property with [IgnoreDataMember]?

like image 31
misha Avatar answered Sep 30 '22 00:09

misha