XmlArrayItem Deserialize to an empty List - c#

I'm getting empty lists when I deserialize one of my List that has been concerted to XML.
I start out with my object GJurisdictions and serialize it to XML
<open511 xml:lang="en" xml:base="http://api.open511.info/" version="v0">
<jurisdictions>
<jurisdiction>
<id>my.id</id>
<languages>
<language>en</language>
</languages>
</jurisdiction>
</jurisdictions>
</open511>
This is exactly what I want but when I try to read it back in Languages is empty.
public class Jurisdiction
{
[XmlElement("id")]
[JsonProperty("id")]
public string Id { get; set; }
[XmlArray("languages")]
[XmlArrayItem("language")]
[JsonProperty("languages")]
public List<String> Languages { get; set; }
}
[XmlRoot("open511")]
public class JurisdictionsBase : Open511Base
{
private List<Jurisdiction> _jurisdictions;
[XmlArray("jurisdictions")]
[XmlArrayItem("jurisdiction")]
[JsonProperty("jurisdiction")]
public List<Jurisdiction> Jurisdictions
{
get { return _jurisdictions ?? (_jurisdictions = new List<Jurisdiction>()); }
set { _jurisdictions = value; }
}
}
The list of jurisdictions serializes perfectly and all the other properties (I edited for clarity) serialize perfectly but the language list is always empty, why?
Specification: http://open511.org/jurisdiction.html
Full Code: https://github.com/doublej42/Open511DotNet/blob/master/Open511DotNet/Jurisdiction.cs

So I didn't give enough information without reading the full source code. My problem was that somewhere else in my project I used some sample code from http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.readxml(v=vs.110).aspx
public void ReadXml (XmlReader reader)
{
personName = reader.ReadString();
}
Do not use the above code
it doesn't move the reader ahead correctly.
As mentioned here http://msdn.microsoft.com/query/dev12.query?appId=Dev12IDEF1&l=EN-US&k=k(System.Xml.XmlReader.ReadString);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.1);k(DevLang-csharp)&rd=true
public void ReadXml(System.Xml.XmlReader reader)
{
_unit = reader.ReadElementContentAsString();
}

Related

Process XML output from API

I am getting an XML return from an Ebay API call. This is actually an Ebay category list of collections. But the problem is, I can't access its collection from XML output. I have attached two pictures - the first one showing debug of XML value returning variable, and the second one showing "InnerList". My main goal is prepare this XML data to store on my database, so I need a clean list of values from XML data. Any ideas?
You could deserialize your xml into your own class/object - Then it might be easier to work with. All i do is put xml tags to a class and i can deserialize it. See the class and method below:
public static T Deserialize<T>(string xmlText)
{
try
{
var stringReader = new System.IO.StringReader(xmlText);
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
catch
{
throw;
}
}
[XmlElement("adress")]
public class Adress
{
[XmlElementAttribute("street_address")]
public string street_address { get; set; }
[XmlElementAttribute("postal_code")]
public string postal_code { get; set; }
[XmlElementAttribute("city")]
public string city { get; set; }
[XmlElementAttribute("country")]
public string country { get; set; }
}
public main()
{
Adress myAdress = Deserialize<Adress>(XMLstring);
}
Hope it helps!
It seems you are using Ebay SDK. Please try code below to process return values.
foreach (CategoryTypeCollection item in categories)
{
item.ItemAt(0).CategoryID = "This is how you access the properties of he returned result";
// THE XML is already parsed for you via SDK, so you don't have to parse it...
// since i wrote foreach loop here, always access itemAt 0th index posiiton
}

Deserialization of serialized data fails

I am trying to deserialize an XML document that I am also serializing at another time. I am using it to store a configuration file.
This is my Code:
namespace OrderTracker
{
[Serializable]
public class AutofillValues
{
private string fileName = Directory.GetCurrentDirectory() + "\\bin\\settings.db";
public ComboBox.ObjectCollection Vendors { get; set; }
public ComboBox.ObjectCollection Products { get; set; }
public ComboBox.ObjectCollection Companies { get; set; }
public void save(AutofillValues afv)
{
if (!File.Exists(fileName))
{
FileStream fs = File.Create(fileName);
fs.Close();
}
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
TextWriter writer = new StreamWriter(fileName);
x.Serialize(writer, afv);
writer.Close();
}
public AutofillValues load()
{
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
TextReader file = new StreamReader(fileName);
AutofillValues av = (AutofillValues)x.Deserialize(file);
file.Close();
return av;
}
}
}
The error message that I am getting when trying to deserialize the file is this;
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
Additional information: There is an error in XML document (2, 2).*
This is the XML document:
<?xml version="1.0" encoding="utf-8"?>
<AutofillValues xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Vendors>
<anyType xsi:type="xsd:string">Test Vendor</anyType>
</Vendors>
<Products>
<anyType xsi:type="xsd:string">Test Product</anyType>
</Products>
<Companies>
<anyType xsi:type="xsd:string">Test Company</anyType>
</Companies>
</AutofillValues>
How can I deserialize the XML file and get back the serialized data?
I just changed this part and it worked for me.
You can not deserialize the XML back, because the class ComboBox.ObjectCollection does not have a standard (parameterless) constructor. This is a limitation of the XmlSerializer class, as stated in this SO post.
There is however another problem with your current code - even if the deserialization somehow works, than you still need to assign the collection to a ComboBox control, which the deserializer still can't do.
Instead of using the ComboBox.ObjectCollection class to store the items, I would suggest using either an array or a list of objects (as #kenlacoste suggested). Such collections can be easily inserted into the ComboBox using
the comboBox.Items.AddRange(arrayOfObjects) method.
Another refactoring would be to extract the serialization logic of the data class. Currently it is confusing to save and load the data, because I presume you want to save/fill the caller object:
save: object.save(object); - you can use the this keyword in the save method
load: object = object.load(); - same here, there is no need to return the value, use the this keyword to fill the existing properties
The changed code:
public class AutofillValues
{
private string fileName = #"d:\settings.db";
public object[] Vendors { get; set; }
public object[] Products { get; set; }
public object[] Companies { get; set; }
public void save()
{
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
// with using there is no need to close the writer explicitely
// second parameter - file is created if it does not exist
using (var writer = new StreamWriter(fileName, false))
{
x.Serialize(writer, this);
}
}
public void load()
{
XmlSerializer x = new XmlSerializer(typeof(AutofillValues));
AutofillValues av = (AutofillValues)x.Deserialize(new StreamReader(fileName));
this.Companies = av.Companies;
this.Vendors = av.Vendors;
this.Products = av.Products;
}
}
IMO the modified code is easier to read and understand:
var afv = new AutofillValues();
afv.load();
//use avf.Products
// or afv.save();
I would also suggest to extract the data that needs to be saved in an extra class, for example:
[Serializable]
public class AutofillValuesData
{
public Object[] Vendors { get; set; }
public Object[] Products { get; set; }
public Object[] Companies { get; set; }
}
In the class AutofillValues remove the three properties and leave just one:
public AutofillValuesData Data { get; set; }
Then the logic can be modified to fill the ComboBox controls from the filled data object. This way your data will not be hardwired to the UI and this would make the code more maintainable. You can use a helper like AutoMapper to remove the repetitive code (like mappig objA.Vendors to objB.Vendors).

Deserialization XML to object with list in c#

I want to deserialize XML to object in C#, object has one string property and list of other objects.
There are classes which describe XML object, my code doesn't work (it is below, XML is at end of my post). My Deserialize code doesn't return any object.
I think I do something wrong with attributes, could you check it and give me some advice to fix it.
Thanks for your help.
[XmlRoot("shepherd")]
public class Shepherd
{
[XmlElement("name")]
public string Name { get; set; }
[XmlArray(ElementName = "sheeps", IsNullable = true)]
[XmlArrayItem(ElementName = "sheep")]
public List<Sheep> Sheeps { get; set; }
}
public class Sheep
{
[XmlElement("colour")]
public string colour { get; set; }
}
There is C# code to deserialize XML to objects
var rootNode = new XmlRootAttribute();
rootNode.ElementName = "createShepherdRequest";
rootNode.Namespace = "http://www.sheeps.pl/webapi/1_0";
rootNode.IsNullable = true;
Type deserializeType = typeof(Shepherd[]);
var serializer = new XmlSerializer(deserializeType, rootNode);
using (Stream xmlStream = new MemoryStream())
{
doc.Save(xmlStream);
var result = serializer.Deserialize(xmlStream);
return result as Shepherd[];
}
There is XML example which I want to deserialize
<?xml version="1.0" encoding="utf-8"?>
<createShepherdRequest xmlns="http://www.sheeps.pl/webapi/1_0">
<shepherd>
<name>name1</name>
<sheeps>
<sheep>
<colour>colour1</colour>
</sheep>
<sheep>
<colour>colour2</colour>
</sheep>
<sheep>
<colour>colour3</colour>
</sheep>
</sheeps>
</shepherd>
</createShepherdRequest>
XmlRootAttribute does not change the name of the tag when used as an item. The serializer expects <Shepherd>, but finds <shepherd> instead. (XmlAttributeOverrides does not seem to work on arrays either.) One way to to fix it, is by changing the case of the class-name itself:
public class shepherd
{
// ...
}
An easier alternative to juggling with attributes, is to create a proper wrapper class:
[XmlRoot("createShepherdRequest", Namespace = "http://www.sheeps.pl/webapi/1_0")]
public class CreateShepherdRequest
{
[XmlElement("shepherd")]
public Shepherd Shepherd { get; set; }
}

Convert json data into datatable

I tried using json.net for converting json data into datatable, but am not able to solve, am newbie with json
code i tried:
string json = JsonConvert.SerializeObject(friend);
friends_info finfo = JsonConvert.DeserializeObject<friends_info>(json);
public class friends_info
{
public friends_info()
{
}
public string name_; // Backing field
public string name
{
get { return name_; } // Getter
set { name_ = value; } // Setter
}
public string id_; // Backing field
public string id
{
get { return id_; } // Getter
set { id_ = value; } // Setter
}
}
where string json="{"data":[{"name":"Angelina Jovy","id":"100000599264453"},{"name":"Luvbhie Rose May Aviles","id":"100001102845189"},{"name":"Nainy Ahuja","id":"100001103300515"},{"name":"Sabrina Reis","id":"100008357430263"}],"paging":{"next":"https://graph.facebook.com/v1.0/1539545690/friends?access_token=CAAGjOBYUDq0BAAFnIgfyfvMftE1ImSEfZCK7R7NdFYw5lnKuddHwqqlm20DTuZCjEeUh2hzMD0KAJpY1ozq3aPuh9nQUHBrXtG0Qu2sd6RwotUQtYj9jtGcMlJEzZCCBLLH8CZBSNQIZAzC2ASOxkYf3JCfwGZA7XSzF5y2iPVDWRCfrl8C4rZAZBzkJiaJwytVvSintYLRfySaunO81fAei&limit=5000&offset=5000&__after_id=enc_AewuVVCxM4Iz1IuazCHob3SZku3BDZ6NeU054UtCU_gc0QDAm2g2VNM__lcbuJNDtm9RmHLU-QCQifFun9H__Zqs"}}"
The class you're deserializing to must match the JSON string.
public class MyData
{
public friends_info[] data { get; set; }
public object paging { get; set; } // you can probably omit this
}
With that deserializing the given JSON string should work.
MyData myData = JsonConvert.DeserializeObject<MyData>(json);
friends_info finfo = myData.data;
Apart from that I'd very much suggest that you look into the C# basics again. Even that little code you posted violates the typical coding conventions.
i m not sure but i think your string is not in correct format it should be like this.
"{'data':[{'name':'Angelina Jovy','id':'100000599264453'},{'name':'Luvbhie Rose May Aviles','id':'100001102845189'},{'name':'Nainy Ahuja','id':'100001103300515'},{'name':'Sabrina Reis','id':'100008357430263'}],'paging':{'next':'https://graph.facebook.com/v1.0/1539545690/friends?access_token=CAAGjOBYUDq0BAAFnIgfyfvMftE1ImSEfZCK7R7NdFYw5lnKuddHwqqlm20DTuZCjEeUh2hzMD0KAJpY1ozq3aPuh9nQUHBrXtG0Qu2sd6RwotUQtYj9jtGcMlJEzZCCBLLH8CZBSNQIZAzC2ASOxkYf3JCfwGZA7XSzF5y2iPVDWRCfrl8C4rZAZBzkJiaJwytVvSintYLRfySaunO81fAei&limit=5000&offset=5000&__after_id=enc_AewuVVCxM4Iz1IuazCHob3SZku3BDZ6NeU054UtCU_gc0QDAm2g2VNM__lcbuJNDtm9RmHLU-QCQifFun9H__Zqs'}}";
if your json string is in correct format then #bstenzel suggestion should work fine.
Thanx

Set XML serialziation resulting doc root

I've got another problem (which might not be an issue in terms of coding problems) but more of principle..been bugging me for a while. I have this c# class, as follows:
namespace SMCProcessMonitor
{
public class Config
{
[XmlElement("Recipient")]
public string recipient;
[XmlElement("Server-port")]
public int serverport;
[XmlElement("Username")]
public string username;
[XmlElement("Password")]
public string password;
[XmlElement("Program")]
public List<Programs> mPrograms = new List<Programs>();
[Serializable]
[XmlRoot("Email-Config")]
public class Email
{
public string Recipient
{
get
{
return SMCProcessMonitor.ConfigManager.mConfigurations.recipient;
}
set
{
SMCProcessMonitor.ConfigManager.mConfigurations.recipient = value;
}
}
public int ServerPort
{
get
{
return SMCProcessMonitor.ConfigManager.mConfigurations.serverport;
}
set
{
SMCProcessMonitor.ConfigManager.mConfigurations.serverport = value;
}
}
public string Username
{
get
{
return SMCProcessMonitor.ConfigManager.mConfigurations.username;
}
set
{
SMCProcessMonitor.ConfigManager.mConfigurations.username = value;
}
}
public string Password { get; set; }
}
}
I can serialize this almost fine. (i recently changed simple get; set; to the full-works as seen above, but when serialising i get something like this;
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Recipient>sd</Recipient>
<Server-port>1234</Server-port>
<Username>dk</Username>
<Password>kdkdk</Password>
</Config>
Basically I want to wrap these 4 tags in an "email-settings" tag.
Add the Serializable() and XmlRoot attributes up to the base class:
[Serializable()]
[XmlRoot("Email-Settings")]
public class Config
There are attributes to control aspects of xml serialization like this, see Controlling XML Serialization Using Attributes.
I think the one you want specifically is XmlRootAttribute.
You'll need to create an EmailSettings class that contains those 4 properties, and then make an instance of the EmailSettings class a member of your Config class.

Categories

Resources