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));
Related
I'm trying to deserialize such an XML
<ErrorResponse xmlns="http://schemas.ipcommerce.com/CWS/v2.0/Rest" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ErrorId>7002</ErrorId>
<HelpUrl>http://docs.nabvelocity.com/hc/en-us/articles/203497757-REST-Information</HelpUrl>
<Messages xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>An invalid security token was provided.</a:string>
</Messages>
<Operation>SignOn</Operation>
<Reason i:nil="true"/>
<ValidationErrors/>
</ErrorResponse>
into such an object with its static method
[XmlRoot("ErrorResponse", Namespace = "http://schemas.ipcommerce.com/CWS/v2.0/Rest")]
public class VelocityException
{
public int ErrorId { get; set; }
public string Operation { get; set; }
[XmlArray("Messages", Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
public string[] Messages { get; set; }
public static VelocityException FromXmlString(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(VelocityException), );
return (VelocityException)serializer.Deserialize(new StringReader(xml));
}
}
however, after deserialization, the array Messages are always null. How do I set up the custom namespace prefix for deserialization of that strings array?
Instead of XmlArray, use XmlArrayItem. Also, remove the "Messages" and use "string" instead since your Messages is a list of "string" (a:string)
This works,
[XmlRoot("ErrorResponse", Namespace = "http://schemas.ipcommerce.com/CWS/v2.0/Rest")]
public class VelocityException
{
public int ErrorId { get; set; }
public string Operation { get; set; }
[XmlArrayItem("string", Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays", IsNullable = false)]
public string[] Messages { get; set; }
public static VelocityException FromXmlString(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(VelocityException));
return (VelocityException)serializer.Deserialize(new StringReader(xml));
}
}
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.
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);
I am trying to deserialize the below XML using C#
<?xml version="1.0" encoding="utf-8"?>
<Invoice>
<Samples>
<Sample>
<AccountId>1e547ae6-9a6d-d18f-958b-22000b83a845</AccountId>
<AccountNumber>55761598808</AccountNumber>
</Sample>
<Sample>
<AccountId>1e547ae6-9a6d-d18f-958b-22000b83a845</AccountId>
<AccountNumber>55761598808</AccountNumber>
</Sample>
</Samples>
</Invoice>
Here are the classes that I have defined to deserialize
[DataContract(Name = "Sample")]
public class Sample
{
[DataMember(Name = "AccountId")]
public string AccountId { get; set; }
[DataMember(Name = "AccountNumber")]
public string AccountNumber { get; set; }
}
[DataContract(Name = "Samples")]
public class Samples
{
[DataMember(Name = "Sample")]
public List<Sample> Sample { get; set; }
}
[DataContract(Name = "Invoice")]
public class Invoice
{
[DataMember(Name = "Samples")]
public Samples Samples { get; set; }
}
The corresponding test case to deserialize is as follows
public void SampleXmlTest()
{
dynamic env = SUT.GetEnvironment();
string dbConnStrUrjanet = (string)env.AvidUtility.UrjanetDB;
XmlSerializer deserializer = new XmlSerializer(typeof(CommonAvidXmlDto.Invoice));
TextReader reader = new StreamReader(#"C:\Users\SJuluru\Desktop\Sample XML\Samplexml.xml");
Object obj = deserializer.Deserialize(reader);
CommonAvidXmlDto.Invoice XmlData4 = (CommonAvidXmlDto.Invoice)obj;
After running the test case debug mode, XmlData4 has null without having the XML data. Kindly help me how to modify this code to work.
DataContract and DataMember are attribute of DataContractSerializer so you shoud replace your serializer msdn or use XmlSerializer's attributes (XmlRoot, XmlElement etc)
Change deserialize classes:
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace ConsoleApp4
{
[XmlRoot(ElementName = "Sample")]
public class Sample
{
[XmlElement(ElementName = "AccountId")]
public string AccountId { get; set; }
[XmlElement(ElementName = "AccountNumber")]
public string AccountNumber { get; set; }
}
[XmlRoot(ElementName = "Samples")]
public class Samples
{
[XmlElement(ElementName = "Sample")]
public List<Sample> Sample { get; set; }
}
[XmlRoot(ElementName = "Invoice")]
public class Invoice
{
[XmlElement(ElementName = "Samples")]
public Samples Samples { get; set; }
}
}
Use below method for deserialize:
private static Invoice LoadInvoice(string fileName)
{
var serializer = new XmlSerializer(typeof(Invoice));
if (!File.Exists(fileName))
{
return null;
}
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return (Invoice)serializer.Deserialize(fs);
}
}
Result:
Help to deal with JSON deserialization correct answer. For example, we have JSON response to the following:
{"variant":"otvet1",
"source":"otvet2",
"items":[
{"list":"512"},
{"vist":"315"},
{"zist":"561"}]}
To deserialize using the following code:
[DataContract]
public partial class ItemsList
{
[DataMember(Name = "list")]
public string lisType { get; set; }
[DataMember(Name = "vist")]
public string vistType { get; set; }
[DataMember(Name = "zist")]
public string zistType { get; set; }
}
[DataContract]
public partial class SourceList
{
[DataMember(Name = "variant")]
public string variantType { get; set; }
[DataMember(Name = "source")]
public string vistType { get; set; }
[DataMember(Name = "items")]
public List <ItemsList> TestItemsList { get; set; }
}
public class JsonStringSerializer
{
public static T Deserialize<T>(string strData) where T : class
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(strData));
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
T tRet = (T)ser.ReadObject(ms);
ms.Close();
return (tRet);
}
}
private static SourceList SourceTempList;
SourceTempList = JsonStringSerializer.Deserialize<SourceList>(e.Result); //in e.Result JSON response
In the previous code, it works, but if you change the JSON response, it does not work ...
New JSON response:
{"variant":"otvet1",
"source":"otvet2",
"items":[3,
{"list":"512"},
{"vist":"315"},
{"zist":"561"}]}
In this case, c # code for deserialization does not work ...
Items in the number 3 appeared, tell me how to deserialize the JSON response to this?
Were available to list vist and zist ...Help me...please
Historically the DataContractJsonSerializer has been seen as broken. The reccomendation is to use JSON.Net http://james.newtonking.com/projects/json-net.aspx
Check out Deserialization problem with DataContractJsonSerializer