Currently I'm using XmlSerializer to serialize and deserialize an object. The xml is generated in an undefined order which is understandable but makes it annoying when comparing versions of the object, since the order of properties is different each time. So for instance I can't use a normal diff tool to see any differences.
Is there an easy way to generate my xml in the same order every time, without writing the ReadXml and WriteXml methods myself? I have a lot of properties on the class, and add new ones every now and again, so would prefer to not have to write and then maintain that code.
(C# .net 2.0)
The XmlElement attribute has an order property. You can use that as a start.
If you need to find the diff in Xml files, you might want to take a look at this.
Decorate your properties with the XmlElementAttribute, setting the Order parameter.
ps: I don't believe the XML generated by the XmlSerializer is in an undefined order. It may be undocumented, but it is known. I believe that in the absence of Order attributes, the XmlSerializer serializes all public Properties, alpha-sorted by prop name, and then all public Fields, alpha-sorted by name.
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.
I'm wondering how to exclude/strip certain properties of given type(s) (or collections of those) from being serialized using Json.NET library?
I tried to write my own contract resolver (inheriting from DefaultContractResolver) with no luck.
I know that I could be done using DataAnnotations, decorating the excluded properties with ScriptIgnoreAttribute, but it's not applicable in my scenario. The objects serialized can be virtually anything, so I don't know which properties to exclude at design-time. I know only the types of properties that should not be serialized.
It looks like a rather simple task, but unfortunately I couldn't find a decent solution anywhere...
BTW - I'm not bound to Json.NET library - if it can easily be done with default/other .NET JSON serializers it'd be an equally good solution for me.
UPDATE
The properties has to be excluded before trying to serialize them. Why?
Basically, the types of objects I'm receiving and serializing can have dynamic properties of type inheriting from IDynamicMetaObjectProvider. I'm not going to describe all the details, but the DynamicMetaObject returned from GetMetaObject method of these objects doesn't have DynamicMetaObject.GetDynamicMemberNames method implemented (throws NotImplementedException...). Summarizing - the problem is those objects (I need to exclude) doesn't allow to enumerate their properties, what Json.NET serializer tries to do behind the scenes. I always end up with NotImplementedException being thrown.
I have tried both the WCF JSON serialization as well as the System.Web.Script.Serialization.JavaScriptSerializer. I have found if you want solid control of the serialization process and do not want to be bound by attributes and hacks to make things work, the JavaScriptSerializer is the way to go. It is included in the .NET stack and allows you to create and register JavaScriptConverter subclasses to perform custom serialization of types.
The only restriction I have found that may cause you a problem is that you cannot easily register a converter to convert all subclasses of Object (aka, one converter to rule them all). You really need to have knowledge of common base classes or preregister the set of types up front by scanning an assembly. However, property serialization is entirely left up to you, so you can decide using simple reflection which properties to serialize and how.
Plus, the default serialization is much much much better for JSON than the WCF approach. By default, all types are serializable without attributes, enums serialize by name, string-key dictionaries serialize as JSON objects, lists serialize as arrays, etc. But for obvious reasons, such as circular trees, even the default behavior needs assistance from time to time.
In my case, I was supporting a client-API that did not exactly match the server class structure, and we wanted a much simpler JSON syntax that was easy on the eyes, and the JavaScriptSerializer did the trick every time. Just let me know if you need some code samples to get started.
Create your own contract resolver, override the method that creates the properties for an object and then filter the results to only include those that you want.
Have you considered using the ShouldSerialize prefix property to exclude the property of your specific type at runtime?
public class Employee
{
public string Name { get; set; }
public Employee Manager { get; set; }
public bool ShouldSerializeManager()
{
return (Manager != this);
}
}
My program creates xslt files and stores the information from custom classes there, this is done dynamically with attributes which mark the classes and properties I want to store in the xslt. This was quite easy because i just had to name the attribute like the property and fill the value with the object's toString() method.
Now I want to somehow reload that Information, create the same classes and fill the properties with those values. But how do i do that with e.g. Enums and other complex types if i don't know the type at compile time? Has to be some sort of parse method..
Any ideas?
If you just want to serialize your objects to XML and then desterilize them, and your objects contain interfaces, generic lists or other complex type you can use very useful serialization library http://www.codeproject.com/KB/XML/sharpserializer.aspx by Pawel Idzikowski.
It is really straight forward and can be very helpful in such cases.
Is there a way in .Net 4 to easily deserialize a stream of mixed objects one by one? I can read to the start of the element for an object I want to deserialize using XmlTextReader.Read(), but have tried many ways to deserialize that specific object unsuccessfully.
The types I want to deserialize can be read as a list of those types without a problem using XmlSerializer, however I want to be able to mix them rather than having input files containing just lists of one object type.
e.g.
<Objects>
<TypeA>...</TypeA>
<TypeB>...</TypeB>
<TypeA>...</TypeA>
<TypeC>...</TypeC>
...
</Objects>
The ordering of the objects in would be random.
Many thanks for any pointers.
I've looked at XmlSerializer, DataContractSerializer and XElement, but could not get them to work for this (although I possibly didn't set those up correctly as I'm not very familiar with them).
You can do that with the XmlSerializer.
However, be careful with the following:
The array you are serializing/deserializing must be declared as an array of "object" (or the base object if all other types inherit from it)
Each type will have "xsi:type" attached to it
You must use [XmlInclude] to include all the type(s) you are ever going to need with the "root" object.
The need to [XmlInclude] all the object types mean that you're not going to be able to dynamically add types to the serialization. You'll need to add [XmlInclude]'s and recompile to include the new type(s).
Your XML, however, will become:
<Objects>
<TypeObj xsi:type="TypeA">...</TypeObj>
<TypeObj xsi:type="TypeB">...</TypeObj>
<TypeObj xsi:type="TypeA">...</TypeObj>
<TypeObj xsi:type="TypeC">...</TypeObj>
:
</Objects>
This is the most flexible and "normal" way of approach XML serialization of multiple types. However, if you need to keep your exact format, you can declare your class this way:
[XmlRoot("Objects")]
public class Objects
{
[XmlElement("TypeA")] public TypeA[] TypeAObjects;
[XmlElement("TypeB")] public TypeB[] TypeBObjects;
[XmlElement("TypeC")] public TypeC[] TypeCObjects;
:
}
[XmlElement] means that all the objects are jumbled up on the same level (different from XmlArray). They do not even have to be in order.
The pitfalls of doing this, however, is that if you want to add a new type, you'll have to modify the "Objects" class.
Not sure if this is helpful, but it might be an idea to take a look at how RestSharp does their deserialization. https://github.com/johnsheehan/RestSharp
Specifilcally Take a look at RestSharp/Deserializers/XmlDeserializer.cs
You would need to create an XmlSerializer for each type. How many types you have and how many times each would get used would determine if it's better to create a new XmlSerializer for each object as you process it, or store them in a Dictionary<string, XmlSerializer> to be reused. The XmlSerializer takes the type in its constructor, and then you can call the Deserialize method, passing it a StringReader that contains the XML string you read from your file. Hopefully that's enough to get you started, but if you need more help I can throw together some sample code ;)
I have few .cs files generated by xsd.exe by a XSD schema.
My problem is that when i try to serialize those classes to xml, the attributes whose values match the default values defined in the xsd schema are not being serialized.
I found out that my problem is solved when i remove [System.ComponentModel.DefaultValueAttribute(typeof(<someType>), "<SomeValue>")]
attribute for the member representing a default field.
So my question isn't there more elegant way to do this? For example is there any way to specify that I want the default values to be serialized anyway?
The short versions is: yes. it looks like that is the simplest approach.
I've tried the "obvious" things (in particular the *Specified and ShouldSerialize* patterns that XmlSerializer supports, but also IsNullable) and it just keeps on not including the value.
The next options would be either IXmlSerializable (which is plain hard), or XmlAttributeOverrides (a duplication of effort) - neither of which is particularly enticing here. I wonder if your current approach is less work? You could of course simply export the WSDL and edit that to remove the default (and generate from the edited version).
As an aside - if this was WCF, there is the [DataMember(EmitDefaultValue = ...)] that does control this; maybe they added this as a feature request?