In all my learning about xml serialisation the samples showed using a public property with a private back store field.
But then I found this:
https://blog.udemy.com/csharp-serialize-to-xml/
I also learned that with c# 3.0 you don't always need the backing store field as it is done behind the scenes.
So should I simplify my code and follow the link and just use public properties?
Explicit private backing fields are completely unnecessary for XmlSerializer, which can only serialize public fields and properties. As long as the backing field is private, XmlSerializer has no way of detecting whether it is explicit or secretly created by the compiler as described in the docs:
When you declare [an auto-implemented property], the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.
If you are only serializing using XmlSerializer (or json.net with DefaultContractResolver.IgnoreSerializableAttribute = true, which is the default), go right ahead and simplify your classes by using auto-implemented properties.
However, do be aware that auto-implemented properties work poorly with [Serializable]. When you mark a type with this attribute, you are indicating that it can be serialized by serializing its internal state -- its public and private fields1 -- rather than its external state -- its public properties. While this attribute is completely ignored by XmlSerializer, certain other serializers support it, including DataContractSerializer, DataContractJsonSerializer and BinaryFormatter. If you add the attribute to a type with auto-implemented properties, the names of the secret "anonymous" backing fields can start to appear in serialization streams created by those serializers. This sometimes leads to problems such as those in the following questions:
Is there a way to make DataContractSerializer output cleaner XML?.
How to remove k__BackingField from json when Deserialize.
DataContractJsonSerializer generating Ghost string to JSON keys?.
Binary Formatter and properties with\without backing fields.
Ignore Non Serialized property in BinaryFormatter Serialization.
So, if you are using auto-implemented properties, my recommendation would be to remove the [Serializable] attribute from your type. You probably don't need it, data contract serialization works better without it, and in any event its use is being deprecated in .NET Core, as shown here and here. (Though reportedly binary serialization is getting implemented to some extent in .NET Core 2.0, see here for details.)
1 Why fields? In the .Net 1.1 time frame, there were still debates about whether serializing private state might be preferable to serializing public state. This is no longer debated, serialization of public state (or of state as specified by some data contract) is preferred.
Related
I'm looking for a Serializer to persist my classes in text format (not binary). But...
I'm already using protobuf for binary serialization. It works pretty fine. As a side note, I would have prefer not to deal with field id (index) like with protobuf.
Before closing or voting to close this question, please consider these points:
The specificity of this question
If other question really apply to my requirements and are not too old
I'm looking for a serializer with the following properties:
Easy to use
Serialize in text (readable) either Json or XML would be fine
Free
Is documented
Support versioning easily (obsolete field, type change, property name change, ...)
Uses Attribute to define items to serialize (or not serialize)
Does not uses an index (ID like Protobuf)
Be able like Protobuf, to deserialize an object directly without any constructor. Be able to instanciate an object either if the object does not have any public constructor and does not have any constructor with no arguments.
Does not require me to change my class or member accessibility, ie:
Does not need default constructor
Can serialize fields
Can skip public property (when marked to do so)
Others points not essential:
The speed is not important
Open source is a nice bonus
Has some examples is a nice bonus
Some examples of what I prefer to not use:
Microsoft XMLSerializer and JsonSerializer does require default constructor.
I have hard time using Microsoft-DataContractSerializer, an easier solution would be welcome.
NOTE: I'm adding this community wiki entry to save someone the loss of time I just went through debugging this problem.
I have a class object with multiple public properties. I can serialize it fine using JSON.net. But when I load the JSON text back and deserialize it using JsonConvert.DeserializeObject<>, some of the fields are set to NULL when they definitely had valid values at the time of serialization. I inspected the serialized JSON string manually and I definitely see values for the NULL properties in the text. Why is this happening?
By default, Json.Net serializes and deserializes only the public members of a class. If you have public getters but private setters for your properties then the properties will be serialized to JSON but not deserialized back to your class.
The easy way to fix this is to make your setters public, but of course that breaks the immutability that private setters provide. If you want to be able to keep your setters private while still being able to deserialize them, you can annotate your properties with [JsonProperty] attributes instead. This will allow the deserializer to "see" them.
Here is a short fiddle to demonstrate: https://dotnetfiddle.net/4nZdGJ
Although it took me a while to hunt down the problem, the answer was simple. The object properties that always had NULL values when deserialized had private setters. I made the setters public and the problem went away.
I need to binary serialize an object that contains a collection of lots of instances of some base class. Each instance could be any of the derived types, and there are really lots of possible derived types (around one hundred). Therefore I don't really want to modify each of these types so that this object could be serialized.
I would even like to avoid adding the default public constructor to all of these types as this would damage the architecture a little bit and would also be really annoying to do (and not really DRY), not speaking of adding Serializable attribute to every public property in these types. And for the same reason writing a custom serializer/surrogate for each of these types is hardly an option.
What I have tried so far:
BinaryFormatter - requires additional attributes for serialized properties
sharpSerializer - requires public default constructor
protobuf-net - requires addtitional attributes for serialized properties
Net serializer - requires addtitional attributes for serialized properties
I have also tried serializing with Json.NET and then saving the result as a byte array (I know, I know), but I ran into an OutOfMemoryException while serializing. This likely means my object is too heavy for text serialization (it takes around 200Mb in memory, but there are lots of elements in the array, lots of properties in each of the element etc).
If it makes any better - all the objects in the collection I need to save have only public properties (I don't need to serialize fields or private properties). And there also is no particular logic in these objects' constructors - only filling the properies.
Is there any way to achieve the serialization/deserialization without modifying the serialized classes?
I don't even know if it is possible to deserialize an object that does not have parameterless constructor (the restriction required by all of the serializers I've met), but it should be as the reflection allows to create instances without calling constructors.
I find the [DataContract] and [DataMember] attributes a bit messy and would rather do this with code in a config method or something. Is this possible?
You don't have to use these attributes at all. DataContractSerializer will serialize all public properties with getter and setter but in case of serializing entities with navigation properties you will easily end with exception due to "cyclic reference".
To avoid that exception you must either use [DataContract(IsReference = true)] on your entity class with DataMember on every property you want to serilize or IgnoreDataMember on every property you don't want to serialize.
The last and the most complex option is avoiding attributes completely and custom classes implementing IDataContractSurrogate to control serialization outside of the type.
You can also write your completely custom serialization process or use XML serialization or binary serialization with all its requirements.
No, the DataContractSerializer is an opt-in serializer - you have to tell it what you want included.
With other serializers you need to use things like NonSerializedAttribute or XmlIgnoreAttribute to tell the serializer to leave things alone.
I know this is a rather old post, but I came here thinking the same thing if there is a way to set all member attributes automatically on some legacy code with public fields and no getters and setters.
What makes it look just a little bit less messy is shortening up the name DataMember:
using DM = System.Runtime.Serialization.DataMemberAttribute;
[DataContract]
public class SomeClass
{
[DM] public bool IsMO;
[DM] public string LabCode;
[DM] public string OrderNumber;
}
Are there any closed or open source projects for a XML serializer for C# that can serialize for the most part any object without the need to pollute my domain objects with tons of attributes? That will also handle serialization of collections built with the internal generics classes? A bonus would be that it can handle serializing an interface type property. Another bonus would be that it can serialize objects that have read-only properties (or atleast with the get accessor marked internal)
Well, first define "advanced", i.e. what specifically do you need that XmlSerializer doesn't have. In terms of POCO, XmlSerializer has an overloaded ctor that accepts all the attributes you could ever want to add, to avoid having to add them to your object model - but it does still require a public parameterless constructor, and only works on public read/write fields/properties. And you should cache/re-use the serializer if you use this approach.
I'm not aware of any like alternatives, simply because in most cases this is "good enough" - and it is often a mistake to try to brute-force your existing domain object into a DTO. It may be simpler and more maintainable to simply map your domain entities onto a new DTO(s) that are attributed (and have appropriate ctor/properties/etc).
Note that for the ctor/properties issue DataContractSerializer has some answers, but this doesn't have as much fine-grained control over what the xml looks like.
You can allow System.Xml.dll to access your internals by using the InternalsVisibleToAttribute.
Thus serializing internal types and/or internal members. Including internal .ctors.
You can also implement IXmlSerializable on classes to customize their serialization (like the container containing interface references).
You do not have to provide the XML serialization attributes on your classes, but provide them as XmlAttributeOverrides instead.
XmlSerializer is almost always exactly what people want, they just don't know that it is as flexible as it really is.