Deserializing individual objects - c#

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 ;)

Related

Binary serialization/deserialization without additional attributes or default public constructor

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.

XMLSerializer: Deserializing as derived type

I've got my fingers crossed that someone out there has a good understanding of the Microsoft XmlSerializer.
Basically, I have built a system for outputting XML on the back of the serializer which is now causing me a lot of hassle and I am trying to avoid a significant re-write.
Introduction
My current system employs a lot of derived classes.
For example,
BaseResponse -> CarParkResponse -> CarParkResponseInherited
BaseResponse and CarParkResponse (both in a library dll) are seperate from CarParkResponseInherited.
As a result, the base classes are ignorent of the derived class.
What I have done
-> Declared derived classes
I appreciate that in order for xmlserializer to do its thing, there are a number of ways to declare dervied classes.
Declare derived classes in base classes using XmlInclude
or
Declared types to be serialised and deserialised in xmlSerialiser. For example:
XmlSerializer serializer = new XmlSerializer(typeof(CarParkResponse), new Type[] { typeof(CarParkParameters), typeof(CarParkInformation) });
I have gone with the latter.
What I am trying to do
Because the derived classes are seperate and they share the same properties, what I am trying to do is serialize the dervied class as the subclass.
In other words deserialize CarParkResponseInherited as a CarParkResponse.
In "CarParkResponseInherited" I am using the declaration XmlTypeAttribute("CarParkResponse").
Initially this causes a problem when serialized
Types 'CarParkResponseInherited' and 'CarParkResponse' both use the XML type name, 'CarParkResponse', from namespace ''. Use XML attributes to specify a unique XML name and/or namespace for the type."
as the type is already in use "CarParkResponse" so I've declased XmlType("Response") in "CarParkResponse" to get around this.
The Problem
I am now trying to Deserialize the XML returned but I'm now getting the following problem.
The specified type was not recognized: name='CarParkResponse', namespace='', at OriginalRequest xmlns=''
Frustratingly the CarParkResponse is there. I am wondering if this is down to the fact I've used XmlType("Response") in the class and the serializer doesn't recognise the class as being type of CarParkResponse
So my question is
Basically is it possible to pass a derived class as a sub class and have it deserialized as the subclass using the XmlSerializer?
I have experimented with the xml produced.
For example, if I don't use the Serialization tags (such as XmlType() etc.) anywhere in my code. The xml produced will produce a carparkresponse element with "type" as an attribute.
The value is "CarParkResponseInherited". I have written some code that removes "Inherited" from the value which does allow it to be deserialized.
This approach is obviously not good so I am hoping there is a good way around this.
So...
if there is anyone out there that has had to patience to read through this post and can help or offer advice it would be most appreciated as I am all out of ideas.
Thanks.
It might be possible to do something using the XmlAttributeOverrides class. It's mostly used for specific property overrides, so it may or may not be the best thing for you.
The long way around would be to go ahead and serialize as the inherited class. Then, if the mappings are the same, deserialize the xml into the base class, and then, re-serialize into what you want.
Depending on how much or how little control you have over the assemblies, you could override the serialization on the inherited class so it does it as the base class.

JSON.NET - exclude properties of a specific type at runtime

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);
}
}

How can i fill my custom classes properties with an xml file?

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.

Any way to make XmlSerializer output xml in a defined order?

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.

Categories

Resources