XmlSerializer - Serialize elements without parent node - c#

this is my first question on stackoverflow, so this is going to be fun!
I've got the following structure that I want to convert to xml. I need to include all the sub elements from the inner object, without the inner object as a node.
class element1
{
element1.1
{
element1.1.1,
element1.1.2,
element1.1.3,
element1.1.4,
}
}
In other words, how can I serialize that to the following?
<element1>
<element1.1.1 />
<element1.1.2 />
<element1.1.3 />
<element1.1.4 />
</element1>
I'm trying different combinations with the xmlelement, XmlIgnore, etc. but non seem to work until now.
Any word of advice would be deeply appreciated!
The code here would be :
[XmlElement("Element1")]
public class Element1
{
[XmlElement("Element11")]
public string Element11 {get;set;}
[XmlElement("Element12")]
public Element12 Element12 {get;set;}
}
public class Element12
{
[XmlElement("element121")]
public string element1{get;set;}
[XmlElement("element122")]
public string element2{get;set;}
[XmlElement("element123")]
public string element3{get;set;}
[XmlElement("element124")]
public string element4{get;set;}
}

You cannot do that. XmlSerializer makes the assumption that the model you want to serialize is shaped roughly like the xml you want. There are some minor tweaks you can do, but this is not one of them. If the problem is that your domain model has an extra layer, then the solution is simple: don't serialize your domain model. Introduce a new set of DTO classes that exist solely for the purpose of xml serialization, and transform your data into the DTO model prior to serialization.

Related

How can you store lists of objects in SQLite.net?

Let us assume I have these two objects
class Customer {
[PrimaryKey]
public string id;
[??????]
public List<int> addresses;
}
and
class Address {
[PrimaryKey, AutoIncrement]
public int id;
public string street;
public int number;
}
Is there a way to use the SQLite.NET ORM to save the Customers object? cause I'm having a really hard time saving lists.
If there is no such way, is there some sort of event I can implement or method I can override so that when an object gets loaded code will trigger?
I was thinking something along the lines of adding [Ignore] above the list of addresses and when the event triggers I can use SQLite.net to load the ids of the addresses from another table
Thanks in advance for any help you can provide
Have a look at this answer here
You can do it with Text blobbed properties from the SQLite-Net Extensions library
So for example in your Model class:
public class Customer
{
[PrimaryKey]
public string id;
[TextBlob("addressesBlobbed")]
public List<int> addresses { get; set; }
public string addressesBlobbed { get; set; } // serialized CoconutWaterBrands
}
from the documentation on Text blobbed properties:
Text-blobbed properties are serialized into a text property when saved and deserialized when loaded. This allows storing simple objects in the same table in a single column.
Text-blobbed properties have a small overhead of serializing and deserializing the objects and some limitations, but are the best way to store simple objects like List or Dictionary of basic types or simple relationships.
Text-blobbed properties require a declared string property where the serialized object is stored.
Text-blobbed properties cannot have relationships to other objects nor inverse relationship to its parent.
A JSON-based serializer is used if no other serializer has been specified using TextBlobOperations.SetTextSerializer method. To use the JSON serializer, a reference to Newtonsoft Json.Net library must be included in the project, also available as a NuGet package.
Hope this helps.

Dynamically reading .json file with multiple objects

An application is providing me a .json file that contains an unknown amount of objects. On top of that, the objects content also changes quite a bit.
Here is an example of a json file:
{
"AVRunning":{
"Description":"Symantec Antivirus Service",
"Status":true
},
"CorrectOU":{
"Description":"Server in Correct OU",
"Status":true
},
"RoleAdGroups":{
"Result":true,
"Group":"Server-Admin"
},
"DefaultAdGroups":[
{
"Result":true,
"Group":"Domain Admins"
},
{
"Result":true,
"Group":"Server-Admins"
},
{
"Result":true,
"Group":"SERVERNAME-ADMINS"
}
]
}
This is just an example of a json file. It could contain many more objects, as well as an unknown amount of content within it.
My question to you all, is how do I serialize this into a JSON object in c# once I read the content in as one gigantic string?
Also, I may be overcomplicationg the process here. Once I read this in, I want to pass the data to my view. If this can't be done in c#, would it be easier to do it in Jquery? Or should it be done there in the first place? The file that I am reading in is a local file, so I can't access the data directly in jquery.
I know JSON.NET is a possible tool, but from what I have read, I am not sure how to create the objects dynamically.
You have to define data types into which you want to deserialize json string:
public class ObjectWithDescriptionAndStatus
{
public string Description;
public string Status;
}
public class ObjectWithResultAndGroup
{
public bool Result;
public string Group;
}
public class MyObject
{
public ObjectWithDescriptionAndStatus AVRunning;
public ObjectWithDescriptionAndStatus CorrectOU;
public ObjectWithResultAndGroup RoleAdGroups;
public IList<ObjectWithResultAndGroup> DefaultAdGroups;
}
This is the simplest example, with all fields marked as public and named exactly as keys in the json (they can have arbitrary names but in that case you have to decorate each field with DataMember attribute and set its Name property to the actual name of the key).
Having data types defined, deserialization is a one-liner:
MyObject myObject = Newtonsoft.Json.JsonConvert.DeserializeObject<MyObject>(json);
jQuery makes it pretty simple (just jQuery.parseJSON(<your string>);).
I imagine JSON.NET has a parse function as well, but I haven't used that library, so I couldn't say for sure!

Changing the entity framework templates

I have some problems while using Entity Framework.
I always use a JSONHelper class to convert a list of string to JSON.
Here is the JSONHelper Class:
public static class JSONHelper
{
public static string ToJSON(this object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public static string ToJSON(this object obj, int recursionDepth)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RecursionLimit = recursionDepth;
return serializer.Serialize(obj);
}
}
This class creates JSON. But sometimes it gives me an error saying that "A circular reference was detected in Entity..........."
So in some of the properties of the classes that entity-framework created for me, I have to use [ScriptIgnore] Attribute. Then it works fine.
Now, let's say I made a small change in database. So I will refresh my ADO.Net Entity Data Model. Then I again have to open all those class files and write [ScriptIgnore].
So, I decided to make a change in template designer. But I could not find the files that entity framework uses to create my POCO classes.
Any Ideas????
Please don't tell me to change the way of converting List to JSON.
I recommend that you use the NewtonSoft.Json serializer. It works very well and has settings options for handling many things, including circular references. There is a lot of good documentation and help available for that serializer. Don't reinvent the wheel.
Circular references are controlled like this:
SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
I believe this answer describes what you need to do.
For any entity which you need to apply the ScriptIgnore attribute, you can make a partial class which does the attribute decoration.
Say your entity is like this
public partial class Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
You can create a separate partial class like this
public interface IEntity
{
[ScriptIgnore]
string Name { get; set; }
}
public partial class Entity:IEntity
{
}
You can achieve this by modifying the T4 template file (.tt file). Take a look at the .tt file in a text editor and you will be able to see where your properties are being created. Insert the [ScriptIgnore] attribute in your template and it will be automatically included when you re-generate your entities.
You might need to include an appropriate 'using' at the top of the template etc.
You can do a lot by editing the T4 template, we used it to automatically have our entities implement INotifyPropertyChanged for all properties.

Deserialize XML Array Where Root is Array and Elements Dont Follow Conventions

The XML I am getting is provided by an outside source so I don't have the ability to easily reformat it. I would like to use xml attributes on my entities instead of having to write a linq query that knows how the XML and entity is formatted. Here is an example:
<?xml version="1.0"?>
<TERMS>
<TERM>
<ID>2013-2</ID>
<DESC>Spring 2013</DESC>
</TERM>
<TERM>
<ID>2013-3</ID>
<DESC>Summer 2013 Jun&Jul</DESC>
</TERM>
</TERMS>
I know the the XMLSerializer expects ArrayOfTerm instead of TERMS for example, but that I can tweak my entity to use a different element name with the xml attributes such as this:
public class TermData
{
[XmlArray("TERMS")]
[XmlArrayItem("TERM")]
public List<Term> terms;
}
public class Term
{
[XmlElement("ID")]
public string id;
[XmlElement("DESC")]
public string desc;
}
and I am deserializing the data like so:
TermData data;
XmlSerializer serializer = new XmlSerializer(typeof(TermData));
using (StringReader reader = new StringReader(xml))
{
data = (TermData)serializer.Deserialize(reader);
}
return View(data.terms);
The problem I am facing is that TERMS is the root and the array itself. If the XML were to have a root element that was not the array, I could edit my TermData class like so and it would deserialize correctly (already tested).
[XmlRoot("ROOT")]
public class TermData
{
[XmlArray("TERMS")]
[XmlArrayItem("TERM")]
public List<Term> terms;
}
Note that using TERMS as the XMLRoot does not work. Right now, my code is throwing
InvalidOperationException: There is an error in XML document (2,2).
InnerException: "<TERMS xmlns=" was not expected.
This would lead me to believe that the XML is not formatted correctly, but from my understanding the example I gave is perfectly valid XML.
This would all be trivial if I could edit the source xml, but there could be tons of other responses like this and I need to be able to flex for whatever I might get. What I'm trying to confirm is whether or not the XMLSerializer can support this type of XML structure. I've tested just about everything and can't get it deserialize without editing the XML. It would also be convenient if I didn't have to define a wrapper class (TermData) to hold the list, but this seems to only work if the xml follows the naming conventions for the serializer (ArrayOfTerm, etc).
Maybe you can try :
[XmlRoot("TERMS")]
public class TermData
{
public TermData()
{
terms = new List<Term>();
}
[XmlElement("TERM")]
public List<Term> terms{get;set;}
}
public class Term
{
[XmlElement("ID")]
public string id{get;set;}
[XmlElement("DESC")]
public string desc{get;set;}
}
Hope this will help,

Xml deserialization, perserving order across different tags

I have xml (which I have no control over) which I needwant to deserialize with the XmlSerializer. My trouble is that I need to preserve the order among two different tags in a single list. Let me give an example:
<users>
<luser>..some more elements..</luser>
<luser>..some more elements..</luser>
<admin>..different elements than in luser</admin>
<luser>..some more elements..</luser>
<admin>..different elements than in luser</admin>
<luser>..some more elements..</luser>
<admin>..different elements than in luser</admin>
<users>
Now, if I deserialze this the straight forward way, I end up with two lists, one for lusers and one for admins. However, the order they appear in is the implicit ID! (Which of course should have been an attribute or element in the xml but alas it is not)
I've tried to make a meta element like this
[XmlElement("luser"),XmlElement("admin")]
public List<Person> Person { get; set; }
with
public class Person
{
public Luser Luser { get; set; }
public Admin Admin { get; set; }
}
where the plan was to check the list to see if the entry a luser or an admin, and have the people wrapper maintain the order of the elements. However multiple XmlElement attributes on a single property seems to be illegal.
Another acceptable solution would be to end up with two lists but where each entry in each list had an ID I could use to get the original order.
I want this to be as clean as possible. Searching through the xml afterwards to find the order, manually extracting the tags, and similar, is something I would avoid and do as a very last resort.
Which of course should have been an attribute...
Then make it an Attribute as soon as you can. Then work with the result.
var doc = XDocument.Load(...);
var fixeruppers = doc
.Descendants("users")
.Elements()
.ToList(); // isolate us from any movements in the doc
int id = 1; // base
foreach (var fixer in fixeruppers)
fixer.SetAttributeValue("Id", id++);
XmlReader readerForDeserialize = doc.CreateReader();
The following will dictate order (with the order:= value), it does not change how the class is serialized.
Imports System.Runtime.Serialization
Imports System.ServiceModel
<DataContract()> _
Public Class MyClass
<DataMember(order:=1)> _
Public Property SomeData() As String
<DataMember(order:=2)> _
Public Property SomeOtherData() As String
End Class

Categories

Resources