XmlSerializer Deserialize list only getting the first item - c#

This is my XML i get from an API:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<datetime>2015-05-18 11:37:32</datetime>
<count>2</count>
<smsleft>40920</smsleft>
<sms><smsid>535041581</smsid><smsid>535041583</smsid></sms>
</response>
This is my class i try to parse it to:
[XmlRoot("response")]
public class SMSResponse
{
[XmlElement("sms")]
public List<smsid> Sms { get; set; }
}
public class smsid
{
[XmlElement("smsid")]
public string SmsID { get; set; }
}
Using this code:
XmlSerializer serializer = new XmlSerializer(typeof(SMSResponse));
using (TextReader reader = new StringReader(response))
{
SMSResponse result = (SMSResponse)serializer.Deserialize(reader);
}
However i only get the first SmsID in the list in my result, not 2 as in the reponse.
What am i doing wrong?

You've declared SmsID as a string, so only a single one can be deserialized. You've declared Sms as a list, but only one exists in your input file.
Try:
[XmlRoot("response")]
public class SMSResponse
{
[XmlArray("sms")]
[XmlArrayItem("smsid")]
public List<string> SmsID { get; set; }
}

Change your code to this
[XmlRoot("response")]
public class SMSResponse
{
[XmlElement("sms")]
public SMS Sms { get; set; }
}
public class SMS
{
[XmlElement("smsid")]
public List<string> SmsID { get; set; }
}

[XmlRoot("response")]
public class SMSResponse
{
[XmlArray(ElementName = "sms")]
[XmlArrayItem(ElementName = "smsid", Type = typeof(smsid))]
public List<smsid> Sms { get; set; }
}
public class smsid
{
[XmlText]
public string SmsID { get; set; }
}

Related

XML deserialization returns list with one empty item

I have the following XML:
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
<accounts>
<items>
<account>
<voornaam><FirstName</voornaam>
<naam>LastName</naam>
<gebruikersnaam>Username</gebruikersnaam>
<internnummer></internnummer>
<klasnummer></klasnummer>
</account>
</items>
</accounts>
With these classes:
public class Accounts
{
public Accounts()
{
items = new List<Account>();
}
[XmlElement]
public List<Account> items { get; set; }
}
public class Account
{
public string voornaam { get; set; }
public string naam { get; set; }
public string gebruikersnaam { get; set; }
public int? internnummer { get; set; }
public int? klasnummer { get; set; }
}
And this code:
var decoded = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><accounts><items><account><voornaam>FirstName</voornaam><naam>LastName</naam><gebruikersnaam></gebruikersnaam><internnummer></internnummer><klasnummer></klasnummer></account></items></accounts>";
XmlSerializer serializer = new XmlSerializer(typeof(Accounts), new XmlRootAttribute("accounts"));
StringReader reader = new StringReader(decoded);
var accounts = (Accounts)serializer.Deserialize(reader);
All I get from this is an Accounts instance with the property Items containing one Account instance with every property null.
You need to specify the items as XML array with XmlArrayAttribute and also with the XmlArrayItemAttribute with (element) item's name: "account" and as Account type. XmlArrayAttribute Example.
public class Accounts
{
[XmlArrayItem(ElementName= "account",
Type = typeof(Account))]
[XmlArray(ElementName="items")]
public List<Account> items { get; set; }
}
Meanwhile, suggest using XmlElementAttribute to specify the element name in XML instead of naming the properties as camelCase.
For the reason why need InternnummerText and KlasnummerText properties you can refer to the question: Deserializing empty xml attribute value into nullable int property using XmlSerializer (will not cover in this answer).
public class Accounts
{
public Accounts()
{
Items = new List<Account>();
}
[XmlArrayItem(ElementName= "account",
Type = typeof(Account))]
[XmlArray(ElementName="items")]
public List<Account> Items { get; set; }
}
[XmlRoot(ElementName="account")]
public class Account
{
[XmlIgnore]
public int? Klasnummer { get; set; }
[XmlIgnore]
public int? Internnummer { get; set; }
[XmlElement(ElementName="voornaam")]
public string Voornaam { get; set; }
[XmlElement(ElementName="naam")]
public string Naam { get; set; }
[XmlElement(ElementName="gebruikersnaam")]
public string Gebruikersnaam { get; set; }
[XmlElement(ElementName="internnummer")]
public string InternnummerText
{
get { return (Internnummer.HasValue) ? Internnummer.ToString() : null; }
set { Internnummer = !string.IsNullOrEmpty(value) ? int.Parse(value) : default(int?); }
}
[XmlElement(ElementName="klasnummer")]
public string KlasnummerText
{
get { return (Klasnummer.HasValue) ? Klasnummer.ToString() : null; }
set { Klasnummer = !string.IsNullOrEmpty(value) ? int.Parse(value) : default(int?); }
}
}
Sample program

Why does deserialized JSON array return null?

I have a string stream returning JSON data from and API that looks like this:
"{\"Recs\":
[
{\"EID\":\"F67_24_6\",\"ReturnPeriod\":\"1\",\"GageStation\":\"NA\"},
{\"EID\":\"T67_24_6\",\"ReturnPeriod\":\"2.37\",\"GageStation\":\"Magueyes Island\"},
{\"EID\":\"R67_24_6\",\"ReturnPeriod\":\"1\",\"GageStation\":\"50147800\"}
]}"
I am trying to deserialize it to return this:
{"Recs":[
{"EID":"F67_24_6","ReturnPeriod":"1","GageStation":"NA"},
{"EID":"T67_24_6","ReturnPeriod":"2.37","GageStation":"Magueyes Island"},
{"EID":"R67_24_6","ReturnPeriod":"1","GageStation":"50147800"}
]}
I am using these public classes to structure the return:
public class New_Events_Dataset
{
public string EID { get; set; }
public string ReturnPeriod { get; set; }
public string GageStation { get; set; }
}
public class NewRootObject
{
public List<New_Events_Dataset> Reqs { get; set; }
}
When I try to apply this later, I basically get a return of {"Reqs":null}. What am I doing wrong here?
var jsonResponse = JsonConvert.DeserializeObject<NewRootObject>(strresult);
string json = new JavaScriptSerializer().Serialize(jsonResponse);
return json;
I think Reqs should be Recs:
public class NewRootObject
{
public List<New_Events_Dataset> Reqs { get; set; }
}
try:
public class NewRootObject
{
public List<New_Events_Dataset> Recs { get; set; }
}
Rename Reqs to Recs and create default constructor of class and instantiate Recs list
public class NewRootObject
{
List<New_Events_Dataset> Recs { get; set; }
public NewRootObject()
{
Recs = new List<New_Events_Dataset>();
}
}

Deserializing XML with different Namespaces UWP

I have following XML-Data:
<?xml version="1.0"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<LastChange>
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/RCS/">
<InstanceID val="0">
<RoomVolumes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=100"/>
<Volume channel="Master" val="100"/>
<Mute channel="Master" val="0"/>
<RoomMutes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=0"/>
</InstanceID>
</Event>
</LastChange>
</e:property>
</e:propertyset>
And here are my classes:
[XmlRoot("propertyset", Namespace = "urn:schemas-upnp-org:event-1-0")]
public class EventPropertySet
{
[XmlElement("property")]
public List<EventProperty> Properties { get; set; }
}
public class EventProperty
{
[XmlElement("LastChange")]
public string LastChange { get; set; }
[XmlElement("SinkProtocolInfo")]
public string SinkProtocolInfo { get; set; }
[XmlElement("IndexerStatus")]
public string IndexerStatus { get; set; }
[XmlElement("SystemUpdateID")]
public string SystemUpdateID { get; set; }
}
Now when I try to deserialize the XML-Data 'LastChange' is always 'null'.
When I modify the class 'EventProperty' like so:
public class EventProperty
{
[XmlElement("LastChange", Namespae = "")]
public string LastChange { get; set; }
[XmlElement("SinkProtocolInfo", Namespae = "")]
public string SinkProtocolInfo { get; set; }
[XmlElement("IndexerStatus", Namespae = "")]
public string IndexerStatus { get; set; }
[XmlElement("SystemUpdateID", Namespae = "")]
public string SystemUpdateID { get; set; }
}
The deserialization throws an exception:
XmlException: ReadElementContentAs() methods cannot be called on an element that has child elements. Line 1, position 103.
Any ideas what I should do?
Sorry, I found the problem. The data behind "LastChange" is normaly a parsed XML-Structure (like this:)
<LastChange><Event xmlns="urn:schemas-upnp-org:metadata-1-0/RCS/"><InstanceID val="0"><RoomVolumes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=100"/><Volume channel="Master" val="100"/><Mute channel="Master" val="0"/><RoomMutes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=0"/></InstanceID></Event></LastChange>
Now when I don't do the "DeParse" with WebUtility.HtmlDecode, everythings works fine.

XML Deserialization results in empty object

I'm attempting to deserialize this XML file into an object
<?xml version="1.0" encoding="utf-8" ?>
<rules version="3">
<emie>
<domain>msdn.microsoft.com</domain>
<domain exclude="false">
bing.com
<path exclude="true">images</path>
</domain>
<domain exclude="true">
news.msn.com
<path exclude="false">pop-culture</path>
</domain>
<domain>timecard</domain>
<domain>tar</domain>
</emie>
</rules>
I have my objects laid out like so
[XmlRoot("rules")]
public class Rules {
[XmlAttribute("version")]
public string Version { get; set; }
[XmlElement("emie")]
public EMIE EMIE { get; set; }
}
public class EMIE {
[XmlArrayItem("Domain")]
public List<Domain> Domains { get; set; }
}
public class Domain {
[XmlAttribute("exclude")]
public bool Exclude { get; set; }
[XmlText]
public string Value { get; set; }
[XmlArrayItem("Path")]
public List<Path> Paths { get; set; }
}
public class Path {
[XmlAttribute]
public bool Exclude { get; set; }
[XmlText]
public string Value { get; set; }
}
And am using this code to deserialize it
static void Main(string[] args) {
XmlSerializer serializer = new XmlSerializer(typeof(Rules));
using (FileStream stream = new FileStream("EM.xml", FileMode.Open)) {
Rules xml = (Rules)serializer.Deserialize(stream);
foreach (Domain d in xml.EMIE.Domains) {
Console.WriteLine(d.Value);
foreach (EnterpriseModeModel.Path p in d.Paths) {
Console.WriteLine(p.Value);
}
}
}
Console.ReadLine();
}
However, my rules.EMIE.Domains object is always empty. When I debug I can see my stream object has a length so it's properly picking up the data in the file but it never fills up the object like I expect it to.
Change the declaration of EMIE as follows
public class EMIE
{
[XmlElement("domain")]
public List<Domain> Domains { get; set; }
}

Xml Deserialize returms null values but xml has values

I saw few topics but no one looks like my problem.
Here is my class:
namespace Framework.Cielo.Models
{
[XmlRoot("transacao", Namespace = "http://ecommerce.cbmp.com.br")]
public class TransactionResponse
{
[XmlAttribute("id")]
public string ID { get; set; }
[XmlAttribute("versao")]
public string Version { get; set; }
[XmlElement("tid")]
public string tid { get; set; }
[XmlElement("pan")]
public string pan { get; set; }
[XmlElement("dados-pedido")]
public EstablishmentOrder Order { get; set; }
[XmlElement("forma-pagamento")]
public PaymentMethod PaymentMethod { get; set; }
[XmlElement("status")]
public TransactionStatusEnum Status { get; set; }
[XmlElement("url-retorno")]
public string ReturnUrl { get; set; }
[XmlElement("autenticacao")]
public Authentication Authentication { get; set; }
}
}
and here is the authentication class
namespace Framework.Cielo.Models
{
[XmlRoot("autenticacao")]
public class Authentication
{
[XmlElement("codigo")]
public int Code { get; set; }
[XmlElement("mensagem")]
public string Message { get; set; }
[XmlIgnore]
public DateTime Date { get; set; }
[XmlElement("data-hora")]
public string FormattedDate
{
get
{
return Date.ToString("yyyy-MM-ddTHH:mm:ss");
}
set
{
DateTime kdc = DateTime.MinValue;
DateTime.TryParse(value, out kdc);
Date = kdc;
}
}
[XmlElement("valor")]
public int Value { get; set; }
[XmlElement("lr")]
public int SecurityLevel { get; set; }
[XmlElement("arp")]
public object arp { get; set; }
[XmlElement("nsu")]
public object nsu { get; set; }
}
}
Here is how I deserialize:
string serializado = File.ReadAllText("req.xml");
var stringReader = new System.IO.StringReader(serializado);
var serializer = new XmlSerializer(typeof(TransactionResponse));
TransactionResponse preAuthResponse = serializer.Deserialize(stringReader) as TransactionResponse;
and here is my XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<transacao versao="1.3.0" id="100" xmlns="http://ecommerce.cbmp.com.br">
<tid>10069930690A16DF1001</tid>
<pan>b1SQ6jpKCDt3n9C0dgD/ZkPQ1Bh+7aJESqr/CwP64P0=</pan>
<dados-pedido>
<numero>100</numero>
<valor>29900</valor>
<moeda>986</moeda>
<data-hora>2013-10-15T00:57:19.032-03:00</data-hora>
<descricao/>
<idioma>PT</idioma>
<taxa-embarque>0</taxa-embarque>
</dados-pedido>
<forma-pagamento>
<bandeira>mastercard</bandeira>
<produto>1</produto>
<parcelas>1</parcelas>
</forma-pagamento>
<status>4</status>
<autenticacao>
<codigo>4</codigo>
<mensagem>Transacao sem autenticacao</mensagem>
<data-hora>2013-10-15T00:57:19.037-03:00</data-hora>
<valor>29900</valor>
<eci>0</eci>
</autenticacao>
<autorizacao>
<codigo>4</codigo>
<mensagem>Transação autorizada</mensagem>
<data-hora>2013-10-15T00:57:19.041-03:00</data-hora>
<valor>29900</valor>
<lr>00</lr>
<arp>123456</arp>
<nsu>661215</nsu>
</autorizacao>
</transacao>
When I run this code, all the elements get right, but not ARP and NSU elements (the last 2 of autorizacao tag)
I really don't know why. This XML comes from a web service and I can't figure out why my deserialize don't work with the 2 last items but works greater with any other element.
I have tried with your code and updated following and it works.
Commented second last <autenticacao> tag.
Rename last tag <autorizacao> to <autenticacao> . May be you are getting wrong xml & last two tags are confusing so I have tried with only one tag.
In Authentication class I have changed type of ARP and NSU otherwise we are getting XMlNode type while deserializing. You can also use string instead of int.
[XmlElement("arp")]
public int arp { get; set; }
[XmlElement("nsu")]
public int nsu { get; set; }

Categories