Xml Deserialize returms null values but xml has values - c#

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

Related

Is there a way to prevent Unexpected character that was encountered while parsing from JSON to C# and XAML error?

I was working on my project and I've come across this error that makes me abit frustrated for no reason:
[TheProblem][1]
[1]: https://i.stack.imgur.com/9Ajtn.png
I have been looking for many ways to solve this even on this very website but none worked so far for C# and Xaml. I am attempting to get JSON files into UPF to look like GUI.
My Vehicle Class:
public class Vehicle
{
[JsonPropertyName("make")]
public string Make { get; set; }
[JsonPropertyName("model")]
public string Model { get; set; }
[JsonPropertyName("VIN")]
public string VIN { get; set; }
[JsonPropertyName("CarType")]
public string CarType { get; set; }
[JsonPropertyName("Seatingcapacity")]
public int Seatingcapacity { get; set; }
[JsonPropertyName("DateObtained")]
public string DateObtained { get; set; }
[JsonPropertyName("NumOfMiles")]
public int NumOfMiles { get; set; }
[JsonPropertyName("InspectionNum")]
public int InspectionNum { get; set; }
[JsonPropertyName("InspectionTech")]
public string InspectionTech { get; set; }
[JsonPropertyName("InspectionDate")]
public string InspectionDate { get; set; }
[JsonPropertyName("InspectIssues")]
public string InspectIssues { get; set; }
[JsonPropertyName("RepairDiscard")]
public string RepairDiscard { get; set; }
[JsonPropertyName("EstPrice")]
public int EstPrice { get; set; }
[JsonPropertyName("EstimatedBy")]
public string EstimatedBy { get; set; }
[JsonPropertyName("EstimatedDate")]
public string EstimatedDate { get; set; }
[JsonPropertyName("SalePrice")]
public int SalePrice { get; set; }
[JsonPropertyName("SalesPerson")]
public string SalesPerson { get; set; }
[JsonPropertyName("SalesDate")]
public string SalesDate { get; set; }
[JsonPropertyName("NegotiatedPrice")]
public string NegotiatedPrice { get; set; }
[JsonPropertyName("NegotiatedPriceApproved")]
public string NegotiatedPriceApproved { get; set; }
}
public class Root
{
[JsonPropertyName("Vehicle")]
public List<Vehicle> Vehicle { get; set; }
}
public class VehicleManager
{
public static async Task<Root> GetVehicles()
{
string target = "Vechile.json";
Root vehicleJson = JsonConvert.DeserializeObject<Root>(target);
return vehicleJson;
}
}
My Vehicle JSON:
{
"make": "Audi",
"model": "A4",
"vin": "1B4HR28N41F524347",
"carType": "Sedan",
"Seatingcapacity": 4,
"DateObtained": "05/15/2010",
"NumOfMiles": 434567,
"InspectionNum": 312345,
"InspectionTech": "Windows",
"InspectionDate": "06/05/2016",
"InspectIssues": "No Issue",
"RepairDiscard": "No Discard",
"EstPrice": 700000,
"EstimatedBy": "Sannaha Vahanna",
"EstimatedDate": "04/27/2010",
"SalePrice": 500000,
"SalesPerson": "Sannaha Vahnna",
"SalesDate": "05/15/2010",
"NegotiatedPrice": "$45,000",
"NegotiatedPriceApproved": "Sannaha Vahnna"
}
}```
As well, my C#
```public sealed partial class MainPage : Page
{
public MainPage()
{
var Vehicles = VehicleManager.GetVehicles();
this.InitializeComponent();
}
private void VehicleGUI_ItemClick(object sender, ItemClickEventArgs e)
{
var vehicle= (Vehicle)e.ClickedItem;
this.Frame.Navigate(typeof(VehicleDetails), vehicle);
}
}```
What to do?
Look at the error message it's giving you. It says the unexpected character is 'V' at line 0 position 0. My guess is the data being passed is not actually the JSON data you think it is - perhaps it's some kind of string representation of a Vehicle (only guessing on that part from the 'V').
The best way to troubleshoot is throw your data being serialized into a local variable and set a break point right before you call the method to serialize. That way you can see exactly what is getting passed.
You may actually want to check out this question, you may be having a similar issue.

C# Searching List of Arrays for specific value and returning related value

I hope this isn't a foolishly simple question. Im very simply trying to figure out how to manipulate a relatively simple table in SQLite through C#.
Im looking to take a parameter and search a List of Arrays for one such array where the parameter matches, and return a related variable within that same array.
For example where an array in the list might be.
Name IATA
Brisbane BNE
The sqlbind:
public static List<Airport> LoadAirports()
{
using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
{
var output = cnn.Query<Airport>("select * from Airport", new DynamicParameters());
return output.ToList();
}
}
The Class:
class Airport
{
int Id { get; set; }
string Name { get; set; }
string LocationName { get; set; }
string IATA { get; set; }
string PortType { get; set; }
string PortOwner { get; set; }
string MotherPort { get; set; }
bool Active { get; set; }
bool IsApplyMeetAndGreet { get; set; }
decimal MeetAndGreet { get; set; }
}
The main Program:
List<Airport> Airports = new List<Airport>();
public FreightCalculator()
{
LoadAirportsList();
string OriginName = OriginInput.Value;
var OriginAirport = Airports.Where(s => s.Name == OriginName);
}
private void LoadAirportsList()
{
Airports = SqliteDataAccess.LoadAirports();
}
Ive tried various combinations of Where, Equals, For each indexing etc. Always getting an error of some kind.
The Error with the above Airports.Where is that the s.Name is inaccessible due to its protection level.
If I do:
var OriginAirport = Airports.Where(Name => Name == OriginName);
I get an error where the operand == cannot be used with Airport and String (Though Name is a string in Airport.)
Im either missing something simple or making this more complicated than it needs to be. Once I find the matching Airport, I need to return the IATA code.
Which I envisage looking like this:
var OriginIATA = OriginAirport.IATA;
Im tired and feeling dumb. Please help :(
Since you declared all members of the Airport class as properties I assume you wanted to expose them publicly.
The error you get is because they are private members and can't be accessed outside the class.
Change "Airport" class to:
class Airport
{
public int Id { get; set; }
public string Name { get; set; }
public string LocationName { get; set; }
public string IATA { get; set; }
public string PortType { get; set; }
public string PortOwner { get; set; }
public string MotherPort { get; set; }
public bool Active { get; set; }
public bool IsApplyMeetAndGreet { get; set; }
public decimal MeetAndGreet { get; set; }
}

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.

Deserialise JSON containing numeric key with Json.NET

I would like to deserialize the following JSON (using Json.NET) to an object, but cannot, as the class name would need to begin with a number.
An example of this is the Wikipedia article API. Using the API to provide a JSON response returns something like this. Note the "16689396" inside the "pages" key.
{
"batchcomplete":"",
"continue":{
"grncontinue":"0.893378504602|0.893378998188|35714269|0",
"continue":"grncontinue||"
},
"query":{
"pages":{
"16689396":{
"pageid":16689396,
"ns":0,
"title":"Jalan Juru",
"extract":"<p><b>Jalan Juru</b> (Penang state road <i>P176</i>) is a major road in Penang, Malaysia.</p>\n\n<h2><span id=\"List_of_junctions\">List of junctions</span></h2>\n<p></p>\n<p><br></p>"
}
}
}
}
How could I deserialize this JSON containing a number which changes based on the article?
It sounds like the Pages property in your Query class would just need to be a Dictionary<int, Page> or Dictionary<string, Page>.
Complete example with the JSON you've provided - I've had to guess at some of the name meanings:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
public class Root
{
[JsonProperty("batchcomplete")]
public string BatchComplete { get; set; }
[JsonProperty("continue")]
public Continuation Continuation { get; set; }
[JsonProperty("query")]
public Query Query { get; set; }
}
public class Continuation
{
[JsonProperty("grncontinue")]
public string GrnContinue { get; set; }
[JsonProperty("continue")]
public string Continue { get; set; }
}
public class Query
{
[JsonProperty("pages")]
public Dictionary<int, Page> Pages { get; set; }
}
public class Page
{
[JsonProperty("pageid")]
public int Id { get; set; }
[JsonProperty("ns")]
public int Ns { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("extract")]
public string Extract { get; set; }
}
class Test
{
static void Main()
{
string text = File.ReadAllText("test.json");
var root = JsonConvert.DeserializeObject<Root>(text);
Console.WriteLine(root.Query.Pages[16689396].Title);
}
}
Related question: Json deserialize from wikipedia api with c#
Essentially you need to changes from using a class for the pages to a dictionary, which allows for the dynamic nature of the naming convention.
Class definitions :
public class pageval
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public string extract { get; set; }
}
public class Query
{
public Dictionary<string, pageval> pages { get; set; }
}
public class Limits
{
public int extracts { get; set; }
}
public class RootObject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
public Limits limits { get; set; }
}
Deserialization :
var root = JsonConvert.DeserializeObject<RootObject>(__YOUR_JSON_HERE__);
var page = responseJson.query.pages["16689396"];
You can implement your own DeSerializer or editing the JSON before you DeSerialize it.

Xml Serialization for list Property doesn't work when one item in the list

<TotalRecords ItineraryCount='1' >
<Recs ItineraryNumber="1" >
<Amount>516.6</Amount>
<TravelTime>940</TravelTime>
<FSegment>
<OutProperty>
<Segment No="1">
<Name>Ronald</Name>
<City>London</City>
<Country>United Kingdom</Country>
</Segment>
<Segment No="2">
<Name>Richard</Name>
<City>
London
</City>
<Country>United Kingdom</Country>
</Segment>
</OutProperty>
</FSegment>
</Recs>
</TotalRecords >
I am serializing xml to object of TotalRecords Class. It works fine when there are more than one segment in the OutProperty but in case of one segment it doesn't serialize into list property.
I have also tried with [XmlArray("")] and [XMlArrayItem("")] but it doesn't work. Anyone have idea?
public class TotalRecords
{
public Recs recs { get; set; }
public string ItineraryCount { get; set; }
}
public partial class Recs
{
public string amountField { get; set; }
public string travelTimeField { get; set; }
public FSegment fSegmentField { get; set; }
public string itineraryNumberField { get; set; }
}
public class FSegment
{
public List<Segment> OutProperty {get;set;}
}
public class Segment
{
public string nameField { get; set; }
public string cityField { get; set; }
public string countryField { get; set; }
}
Try to use the following for your Classes and their Properties:
[DataContract]
public class Contact
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
Hacking like this helps in many cases, perhaps in your too (converting List to array):
public class FSegment
{
[XmlIgnore]
public List<Segment> OutProperty {get;set;}
[XmlArray("OutProperty");
public Segment[] _OutProperty
{
get { return OutProperty.ToArray(); }
set { OutProperty = new List<Segment>(value); }
}
}
I am not exactly sure how your provided class definition worked previously without any XML attribute/element definitions since your variable names are not the same as the XML identifiers, meaning that the serialization wouldn't populate the properties that it couldn't find a name for.
Nether the less, the main issue here is that you are trying to put a list into a normal property.
From the XML provided, OutProperty is a single sub element of FSegment and Segment is an array of sub elements of OutProperty, but in your provided code, you tried to make Segment an array sub element of FSegment.
The correct structure of the class definition should be as follows (also including the XML definitions)
[System.Xml.Serialization.XmlRoot(ElementName="TotalRecords")]
public class TotalRecords
{
[System.Xml.Serialization.XmlElement(ElementName="Recs")]
public Recs recs { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryCount")]
public string ItineraryCount { get; set; }
}
public partial class Recs
{
[System.Xml.Serialization.XmlElement(ElementName = "Amount")]
public string amountField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "TravelTime")]
public string travelTimeField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "FSegment")]
public FSegment fSegmentField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryNumber")]
public string itineraryNumberField { get; set; }
}
public class FSegment
{
[System.Xml.Serialization.XmlElement(ElementName = "OutProperty")]
public SegmentList OutProperty { get; set; }
}
public class SegmentList
{
[System.Xml.Serialization.XmlElement(ElementName = "Segment")]
public List<Segment> segmentField { get; set; }
}
public class Segment
{
[System.Xml.Serialization.XmlElement(ElementName = "Name")]
public string nameField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "City")]
public string cityField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "Country")]
public string countryField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "No")]
public int segmentNoField { get; set; }
}
Please note that in the above structure, Segment is a list object under the OutProperty object, which resides under the FSegment object.
Using this class structure to load your XML produces the (assumed) correct data in the created objects.
Using the XML definitions allows you to decouple the actual names of class properties from what they are called in the XML data. This allows you to changes the one or the other without affecting the other one, which is useful when you don't control the creation of the XML data.
If you don't want all the XML definitions in your code, change the names of the classes so that you can name your properties the same as what they are called in the XML file. That will allow you couple everything directly

Categories