Deserialise XML with parameters to object - c#

I have this simple xml that I just can't deserialise to an object, there are something wrong with my model classes. I just Receive an empty object.
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
\n<response>
\n<lst name=\"responseHeader\">
<int name=\"status\">0</int>
<int name=\"QTime\">20596</int>
</lst>\n
</response>\n"
i serialize like this:
var x = result.Content;
XmlSerializer serializer = new XmlSerializer(typeof(response));
StringReader rdr = new StringReader(x);
response resultingMessage =
(response)serializer.Deserialize(rdr);
and my model classes look like:
[XmlType("response")]
public class response
{
[XmlElement("responseHeader")]
public string Name { get; set; }
public List<lst> Lst { get; set; }
}
public class lst
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("int")]
public List<Int> Int { get; set; }
}
public class Int
{
[XmlElement("status")]
public int status { get; set; }
[XmlElement("QTime")]
public int QTime { get; set; }
}

Couple things to be corrected.
You need to clean the Xml
XmlSerializer serializer = new XmlSerializer(typeof(response));
StringReader rdr = new StringReader(xmlString.Replace(#"\n",String.Empty).Replace(#"\'","'"));
response resultingMessage =
(response)serializer.Deserialize(rdr);
Secondly, You data structure require some changes. For example, response doesn't require a name. It needs to be part of lst. Also it is an attribute, not an element. Hence needs to be decorated with [XmlAttribute]
[XmlType("response")]
public class response
{
[XmlElement("lst")]
public List<lst> Lst { get; set; }
}
public class lst
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("int")]
public List<Int> Int { get; set; }
}
public class Int
{
[XmlAttribute(AttributeName="name")]
public string Name { get; set; }
[XmlText]
public string Text { get; set; }
}
Output

try like this,
/*
var x = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<response>\n<lst name=\"responseHeader\"><int name=\"status\">0</int><int name=\"QTime\">20596</int></lst>\n</response>\n";
*/
var x = result.Content;
x= x.Replace("\\n", string.Empty).Replace("\\", string.Empty);
XmlSerializer serializer = new XmlSerializer(typeof(response));
StringReader rdr = new StringReader(x);
response resultingMessage =
(response)serializer.Deserialize(rdr);
sometimes extra characters can cause the conversion issue.

Related

Deserializing a JSON to c# object when key contains dollar($)(Metadata)

So i'm getting a response like this
{"$id":"1","success":true,"errors":{"$id":"2","$values":[]}}
how can i convert this into to a c# object, tried using this(http://json2csharp.com/) tool to make an output but it doesn't make sense
this is what i'm getting
x
public class Errors
{
public string __invalid_name__$id { get; set; }
public List<object> __invalid_name__$values { get; set; }
}
public class RootObject
{
public string __invalid_name__$id { get; set; }
public bool success { get; set; }
public Errors errors { get; set; }
}
I'm kinda new to c#, any inputs would be deeply appreciated, i basically need access to success key variable
You need to add [JsonProperty] attribute to every property that key name started with dollar $
public class Errors
{
[JsonProperty("$id")]
public string id { get; set; }
[JsonProperty("$values")]
public List<object> values { get; set; }
}
public class RootObject
{
[JsonProperty("$id")]
public string id { get; set; }
public bool success { get; set; }
public Errors errors { get; set; }
}
Because the $ indicates metadata, not an actual data field. so you have to modify your JsonSerializerSettings to ignore MetadataPropertyHandling.
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
And finally deserialize your json to above class objects.
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(json, settings);
Here I created a sample console app for demonstration purpose that shows how above code will work.
class program
{
public static void Main()
{
string json = File.ReadAllText(#"Path to your json file");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(json, settings);
Console.WriteLine("id: " + rootObject.id);
Console.WriteLine("success: " + rootObject.success);
Console.WriteLine("errors.id: " + rootObject.errors.id);
Console.WriteLine("errors.values: " + string.Join(",", rootObject.errors.values));
Console.ReadLine();
}
}
Output:
Well, What you can do is
public class Errors
{
[JsonProperty(PropertyName = "$id")]
public string id { get; set; }
[JsonProperty(PropertyName = "$values")]
public List<object> values { get; set; }
}
public class RootObject
{
[JsonProperty(PropertyName = "$id")]
public string id { get; set; }
public bool success { get; set; }
public Errors errors { get; set; }
}
You need your object attributes to match you json string ($id instead of _invalid_name_$id), then you can use:
JsonConvert.DeserializeObject<RootObject>(jsonString);
Here is a simple class to serialize json string from object or to object (T). May de/serialize array(list) of objects.
public class HelperSerializer<T> where T: class
{
public static string WriteFromObject(T source)
{
using (var ms = new MemoryStream()) {
var ser = new DataContractJsonSerializer(typeof(T));
ser.WriteObject(ms, source);
byte[] json = ms.ToArray();
return Encoding.UTF8.GetString(json, 0, json.Length);
}
}
// Deserialize a JSON stream to an object.
public static T ReadToObject(string json)
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var ser = new DataContractJsonSerializer(typeof(T));
return ser.ReadObject(ms) as T;
}
}
}
Use persons = HelperSerializer<List<Person>>.ReadToObject(json);
and var json = HelperSerializer<List<Person>>.WriteFromObject(persons);

How to Deserialize an xml element with only attributes in C#?

I am using System.Xml.Serialization.XmlSerializer class.I need to Deserialize the following XML in C#:
<message from="abc" to="xyz" xml:lang="en" id="Vx4Ix-14" type="chat">
<received xmlns="urn:xmpp:receipts" id="9beea4d7-aa1e-4f3c-929c-712b56164b63"/>
</message>
Following is my Class to deserialize it :
[XmlRoot(ElementName = "message")]
public class Message
{
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
[XmlAttribute(AttributeName = "from")]
public string From { get; set; }
[XmlAttribute(AttributeName = "to")]
public string To { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "xml:lang")]
public string Language { get; set; }
[XmlElement(ElementName = "received", Namespace = "urn:xmpp:receipts")]
public Received Received { get; set; }
}
public class Received
{
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
The "received" xml element has only attributes and I want te deserialize that element to get "id" value of that element.
But when I use the above class to Deserialize , I get all the values except "id" attribute value of "received" xml element. I get the value of Received property as null.
Please let me know what is wrong with my class?
This is my Deserializer Method:
public static T Deserialize<T>(string xml)
{
T deserializedObject = default(T);
try
{
var serializer = new XmlSerializer(typeof(T));
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
deserializedObject = (T)serializer.Deserialize(memoryStream);
}
return deserializedObject;
}
catch (Exception)
{
return deserializedObject;
}
}
Your class looks good and also works for me. Maybe you're not using the deserializer correctly!? I successfully tried it with your XML like this:
var serializer = new XmlSerializer(typeof(Message));
var message = (Message)serializer.Deserialize(
new FileStream(#"C:\Users\homann.k\Desktop\test.xml", FileMode.Open, FileAccess.Read));

Parse JSON in response to the existing request

Hi I have a response from the web service and i would like to have a single url from the response.
My response is in the below format.
[{"cdn_streaming_uri": "9e849cfbb2e157-22558a0600b387d0abe240fe5.r73.stream..rackcdn.com", "name": "test1", "cdn_ios_uri": "d3d4c27-22558a0600b387d0abc071d0ae240kcdn.com", "cdn_ssl_uri": "https://990fea26e-22558a0600b387d0abc071d0ae240fe5.ssl.cdn.com", "cdn_enabled": false, "ttl": 259200, "log_retention": false, "cdn_uri": "99b56a009-22558a0600b3c071d0ae240fe5.r73.n.com"}, {"cdn_streaming_uri": "74ec8c-d5edc6cad91792413b1b134fde.r46.stcdn.com", "name": "test2", "cdn_ios_uri": "d05437e44-d5edc61792413b1b134fde.iosr.cdn.com", "cdn_ssl_uri": "https://a1c2ebbf5-d5edc6cd91792413b1b134fde.scdn.com", "cdn_enabled": false, "ttl": 259200, "log_retention": false, "cdn_uri": "72ffd-d5edc6ca16852413b1b134fde.cdn.com"}, {"cdn_streaming_uri": "93665b76-550971032c2a22cdn.com", "name": "test3", "cdn_ios_uri": "ca6b-550971032c2fbf19452d6a.iosr.cf2.rackcdn.com", "cdn_ssl_uri": "https://c7c39-550971032cbf19452d6cdn.com", "cdn_enabled": true, "ttl": 86400, "log_retention": true, "cdn_uri": "68fc6d831a94-550971032c252d6a.r3cdn.com"}]
I need to the "cdn_streaming_uri" for the name "test3".
You can view the JSON parser in http://json.parser.online.fr/
How do i parse it?
Here is my code:
public static object getTokenResponse(String PrivateURL, string ResponseType)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(PrivateURL +"?format=JSON");
request.Method = "GET";
request.Headers.Add("X-Auth-Token", id);
//request.ContentType = "application/XML";
HttpWebResponse resp1;
try
{
resp1 = (HttpWebResponse)request.GetResponse();
}
catch (Exception exp)
{
string[] st = new string[0];
return st;
}
StreamReader reader = new StreamReader(resp1.GetResponseStream());
string secondresponse = reader.ReadToEnd();
Console.WriteLine(secondresponse);
reader.Close();
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object obj1 = json_serializer.DeserializeObject(secondresponse);
}
I could see the response in obj1.
The best approach, I think, is to create class which will represent your response. The easiest way is to use Visual Studio's EDIT -> Paste Special -> Paste JSON As Classes option:
You just copy your response and paste it as JSON classes. Visual studio will generate model for you. In this particular case the result will be:
namespace ConsoleApplication91
{
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string cdn_streaming_uri { get; set; }
public string name { get; set; }
public string cdn_ios_uri { get; set; }
public string cdn_ssl_uri { get; set; }
public bool cdn_enabled { get; set; }
public int ttl { get; set; }
public bool log_retention { get; set; }
public string cdn_uri { get; set; }
}
}
which, of course, does not look very nice, but you're always welcome to refactor this code. When you have your model you download your response, parse it and get what you need using linq, for example:
using (var client = new WebClient())
{
var url = "your service url";
var serializer = new JavaScriptSerializer();
// Response in JSON format
var respJson = client.DownloadString(url);
// Deserialized response
var resp = serializer.Deserialize<Rootobject>(respJson);
// Your requested result
var result = resp.Property1.FirstOrDefault(o => o.name == "test3").cdn_streaming_uri;
}
EDITS:
After refactoring (using DataMember attributes and removing redundant model objects) you can have the following model:
[DataContract]
public class Model
{
[DataMember(Name = "cdn_streaming_uri")]
public string CdnStreamingUri { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "cdn_ios_uri")]
public string CdnIosUri { get; set; }
[DataMember(Name = "cdn_ssl_uri")]
public string CdnSslUri { get; set; }
[DataMember(Name = "cdn_enabled")]
public bool CdnEnabled { get; set; }
[DataMember(Name = "ttl")]
public int Ttl { get; set; }
[DataMember(Name = "log_retention")]
public bool LogRetention { get; set; }
[DataMember(Name = "cdn_uri")]
public string CdnUri { get; set; }
}
After some research I've figured out that JavascriptSerializer is a little deprecated and it does not support any kind of DataMemberAttributes. So I would recommend to use DataContractJsonSerializer. It is little messier than JavascriptSerializer but I think it's fine. If you do not care about any code conventions you can peacefully use the firs provided option (with JavaScriptSerializer and no DataMember attributes). And do not forget to update result query:
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(respJson)))
{
var serializer = new DataContractJsonSerializer(typeof(Model[]));
var resp = serializer.ReadObject(ms) as Model[];
var result = resp.FirstOrDefault(o => o.Name == "test3").CdnStreamingUri;
}
But, also, if you don't want to use linq (which I'm still strongly recommend) you can create some function which will find the CdnStreamingUri you need:
public static class Extensions
{
public static string GetCdnStreamingUriFor(this Model[] input, string name)
{
foreach (var model in input)
{
if (model.Name == name)
return model.CdnStreamingUri;
}
return string.Empty;
}
}
And your result query will look like:
var result = resp.GetCdnStreamingUriFor("test3");
P.S.
Full list of all used namespaces:
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Runtime.Serialization;
I recommend you to generate class for that json, like the following (http://json2csharp.com/ ):
public class RootObject
{
public string cdn_streaming_uri { get; set; }
public string name { get; set; }
public string cdn_ios_uri { get; set; }
public string cdn_ssl_uri { get; set; }
public bool cdn_enabled { get; set; }
public int ttl { get; set; }
public bool log_retention { get; set; }
public string cdn_uri { get; set; }
}
After that you can deserialize strongly typed object http://msdn.microsoft.com/en-us/library/bb355316(v=vs.110).aspx

How to deserialize XML string fragment?

I have an object that has some properties that are XML string fragments. I want to take those and further deserialize them into objects for easier use. How can I do that using the .NET XML Serializer?
Here's an example of the XML string fragment:
<Addr1></Addr1>
<Addr2></Addr2>
<Addr3></Addr3>
<Addr4></Addr4>
<City></City>
<State></State>
<PostalCode></PostalCode>
<Country></Country>
So far my attempts have resulted in this exception:
<Addr1 xmlns=''> was not expected.
If you want to deserialize the fragments into objects I assume you have a strongly typed object so you could just create a helper method to add a root element using the type name of the object you are trying to deserialize
Example:
public T DeserializeFragment<T>(string xmlFragment)
{
// Add a root element using the type name e.g. <MyData>...</MyData>
var xmlData = string.Format("<{0}>{1}</{0}>", typeof(T).Name, xmlFragment);
var mySerializer = new XmlSerializer(typeof(T));
using (var reader = new StringReader(xmlData))
{
return (T)mySerializer.Deserialize(reader);
}
}
Usage:
public class MyData
{
public string Addr1 { get; set; }
public string Addr2 { get; set; }
public string Addr3 { get; set; }
public string Addr4 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
string fragment = #"<Addr1>2</Addr1>
<Addr2>2</Addr2>
<Addr3>2</Addr3>
<Addr4>2</Addr4>
<City>2</City>
<State>2</State>
<PostalCode>2</PostalCode>
<Country>2</Country>";
var result = DeserializeFragment<MyData>(fragment);

Passing the object of FileUpload success callback to Controller Action Method

JSON String
[{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"},{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"},{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"},{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"}]
View Model
public class EbayEarnings_Temp
{
public String Program { get; set; }
public DateTime Date { get; set; }
public DateTime TimePlus { get; set; }
public String Campaign { get; set; }
public int Clicks { get; set; }
public decimal EPC { get; set; }
public decimal Earnings { get; set; }
public String CampaignID { get; set; }
public String Impression { get; set; }
public string Status { get; set; }
}
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(EbayEarnings_Temp));
var c = (EbayEarnings_Temp)serializer.ReadObject(jsonString);
I am getting this error
Unexpected character encountered while parsing value: S. Path '', line 0, position 0.
Message is json object not list. You must have integrated serializer or serialize json object in action manually.
I think it must look like this:
public ActionResult action(Object Message)
{
// deserialise if Object Message is a string
var serializer = new JavaScriptSerializer();
var c = serializer.Deserialize<YourClass>(Message);
// deserialise if Object Message is a JsonObject
var serializer = new DataContractJsonSerializer(typeof(YourClass));
var c = (YourClass)serializer.ReadObject(Message);
return PartialView(Message);
}
or another solution:
I use library Newtonsoft.Json. If you're going to use it in your case it would look like:
...
MyClass m = JsonConvert.DeserializeObject<Message>(message.ToString());
var status = m.Status; //...and so on

Categories