Converting ordinary string to object - c#

Is it possible to convert ordinary string like:
"Data: {
id: '288dsbshbdas8dsdsb',
data: '2pm'
}"
to:
Data: {
id: '288dsbshbdas8dsdsb',
data: '2pm'
}
Have tried like that:
string input = "Data: {id: '288dsbshbdas8dsdsb', data: '2pm'};
var output = Convert.ChangeType(input, TypeCode.Object);
But this still returns string?

Using NewtonSoft JsonTextWriter, and JsonTextReader You can easly write and read this kind of string.
For writing your must use JsonTextWriter property:
writer.QuoteName = false;
writer.QuoteChar = '\'';
To read to custom configuration is needed.
using System;
using System.IO;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var objSource= new RootObject{
Data= new Data{
id="123456",
data="FooBar"
}
};
var serializer = new JsonSerializer();
var stringWriter = new StringWriter();
var writer = new JsonTextWriter(stringWriter);
writer.QuoteName = false;
writer.QuoteChar = '\'';
serializer.Serialize(writer, objSource);
var input= stringWriter.ToString();
Console.WriteLine(input);
JsonTextReader reader = new JsonTextReader(new StringReader(input));
var result = serializer.Deserialize<RootObject>(reader);
result.Dump();
}
public class Data
{
public string id { get; set; }
public string data { get; set; }
}
public class RootObject
{
public Data Data { get; set; }
}
}
live demo
Disclaimer: As Jodrell noticed it return a "RootObject".
The writer will return {Data:{id:'123456',data:'FooBar'}}
instead of Data:{id:'123456',data:'FooBar'} Notice the extra {} around the string.
The string manipulation needed to get from one too the other is minor enought.

Related

By pass XmlElement serilization inside a Property with XmlText attribute

I have a class with a string property.
[Serializable]
public class Gather
{
[XmlAttribute("action")]
public string Action { get; set; }
[XmlAttribute("method")]
public string Method { get; set; }
[XmlAttribute("timeout")]
public string Timeout { get; set; }
[XmlAttribute("finishOnKey")]
public string FinishOnKey { get; set; }
[XmlElement]
public Say Say;
}
[Serializable]
public class Say
{
[XmlText]
public string Value;
}
I was doing xml serilization successfully from the following code then i got to know that inside Value property of Say class i need to pass plain xml some time
private string GetSpeechwithGatherXml(string value)
{
Say speechToText = new Say { Value = value };
Gather gather = new Gather
{
Action = txtCallback.Text,
Method = "Get",
Timeout = Convert.ToInt32(numericMaxTime.Value).ToString(),
FinishOnKey = "#",
Say = speechToText
};
GatherResponse response = new GatherResponse { Gather = gather };
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(response.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, response, emptyNamespaces);
return stream.ToString();
}
}
But xml tags are changing to < and > understandingly.
Any way I can by-pass this behavior in one propery (Value of Say class)
I wanted to send something like
<Response>
<Say>John’s phone number is, <say-as interpret-as="telephone">1234</say-as></Say>
</Response>
which is a valid xml

C# deserialize xml array of different types into multiple arrays

I have the following xml:
<Applications>
<AccessibleApplication></AccessibleApplication>
<AccessibleApplication></AccessibleApplication>
<EligibleApplication></EligibleApplication>
<EligibleApplication></EligibleApplication>
</Applications>
Is there a way to deserialize this into a C# object so that the AccessibleApplications and EligibleApplications are two separate arrays? I tried the following but get an exception because "Applications" is used more than once.
[XmlArray("Applications")]
[XmlArrayItem("AccessibleApplication")]
public List<Application> AccessibleApplications { get; set; }
[XmlArray("Applications")]
[XmlArrayItem("EligibleApplication")]
public List<Application> EligibleApplications { get; set; }
The exception is:
The XML element 'Applications' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.
Is this possible to do?
Thanks!
Edit: I forgot to mention that I do not want to have an "Applications" class just for the sake of providing a container object for the two arrays. I have several situations like this and I don't want the clutter of these classes whose only purpose is to split up two arrays of the same type.
I was hoping to be able to deserialize the two arrays into an outer object using some sort of tag like [XmlArrayItem="Application/AccessibleApplication"] without creating an "Applications" class.
I've found a fairly neat way to do this, first make a class like this:
using System.Xml.Serialization;
[XmlRoot]
public class Applications
{
[XmlElement]
public string[] AccessibleApplication;
[XmlElement]
public string[] EligibleApplication;
}
Notice how the elements are individual arrays. Now using this class (I had my XML in a separate file hence the XmlDocument class).
var doc = new XmlDocument();
doc.Load("../../Apps.xml");
var serializer = new XmlSerializer(typeof(Applications));
Applications result;
using (TextReader reader = new StringReader(doc.InnerXml))
{
result = (Applications)serializer.Deserialize(reader);
}
Now to prove this works you can write this all in to a console app and do a foreach to print all the values in your arrays, like so:
foreach (var app in result.AccessibleApplication)
{
Console.WriteLine(app);
}
foreach (var app in result.EligibleApplication)
{
Console.WriteLine(app);
}
You can use XmlElement attribute to deserialize to different lists:
public class Applications
{
[XmlElement("AccessibleApplication")]
public List<Application> AccessibleApplications { get; set; }
[XmlElement("EligibleApplication")]
public List<Application> EligibleApplications { get; set; }
}
public class Application
{
[XmlText]
public string Value { get; set; }
}
So for a sample XML:
<Applications>
<AccessibleApplication>xyz</AccessibleApplication>
<AccessibleApplication>abc</AccessibleApplication>
<EligibleApplication>def</EligibleApplication>
<EligibleApplication>zzz</EligibleApplication>
</Applications>
The following snippet would output the below:
using (var reader = new StreamReader("XMLFile1.xml"))
{
var serializer = new XmlSerializer(typeof(Applications));
var applications = (Applications)serializer.Deserialize(reader);
Console.WriteLine("AccessibleApplications:");
foreach (var app in applications.AccessibleApplications)
{
Console.WriteLine(app.Value);
}
Console.WriteLine();
Console.WriteLine("EligibleApplications:");
foreach (var app in applications.EligibleApplications)
{
Console.WriteLine(app.Value);
}
}
Output:
AccessibleApplications:
xyz
abc
EligibleApplications:
def
zzz
You can use this class to create objects from strings, creating strings from objects and create byte [] from objects
StringToObject
var applicationObject = new XmlSerializerHelper<Applications>().StringToObject(xmlString);
ObjectToString
var xmlString = new XmlSerializerHelper<Applications>().ObjectToString(applicationObject);
ObjectToByteArray
var byteArray = new XmlSerializerHelper<Applications>().ObjectToByteArray(applicationObject);
The XmlSerializerHelper:
namespace StackOverflow
{
public class XmlSerializerHelper<T> where T : class
{
private readonly XmlSerializer _serializer;
public XmlSerializerHelper()
{
_serializer = new XmlSerializer(typeof(T));
}
public T ToObject(string xml)
{
return (T)_serializer.Deserialize(new StringReader(xml));
}
public string ToString(T obj, string encoding)
{
using (var memoryStream = new MemoryStream())
{
_serializer.Serialize(memoryStream, obj);
return Encoding.GetEncoding(encoding).GetString(memoryStream.ToArray());
}
}
public byte[] ToByteArray(T obj, Encoding encoding = null)
{
var settings = GetSettings(encoding);
using (var memoryStream = new MemoryStream())
{
using (var writer = XmlWriter.Create(memoryStream, settings))
{
_serializer.Serialize(writer, obj);
}
return memoryStream.ToArray();
}
}
private XmlWriterSettings GetSettings(Encoding encoding)
{
return new XmlWriterSettings
{
Encoding = encoding ?? Encoding.GetEncoding("ISO-8859-1"),
Indent = true,
IndentChars = "\t",
NewLineChars = Environment.NewLine,
ConformanceLevel = ConformanceLevel.Document
};
}
}
}
Your Class:
[XmlRoot]
public class Applications
{
[XmlElement("AccessibleApplication")]
public string[] AccessibleApplication { get; set; }
[XmlElement("EligibleApplication")]
public string[] EligibleApplication { get; set; }
}
Or
[XmlRoot]
public class Applications
{
[XmlElement("AccessibleApplication")]
public List<string> AccessibleApplication { get; set; }
[XmlElement("EligibleApplication")]
public List<string> EligibleApplication { get; set; }
}
Cheers.

Error when deserializing

I'm trying to write some code to deserialize an XML file. I've looked around a bit and found something which has led me to the following method:
public static void Deserialize(string filePath)
{
RootObject ro = null;
string path = filePath;
XmlSerializer serializer = new XmlSerializer(typeof(RootObject));
StreamReader reader = new StreamReader(path);
ro = (RootObject) serializer.Deserialize(reader);
reader.Close();
}
But all I get is this error and I'm not sure what's causing it:
There is an error in XML document (2, 2).
The RootObject you see in Deserialize() is this one: I'm new to XMl serializing/deserializing so I'm not sure if I've defined it 100% correctly.
public class RootObject
{
public Services Services { get; set; }
}
public class Services
{
public Service TileMapService { get; set; }
}
public class Service
{
public string Title { get; set; }
public string href { get; set; }
}
I'm using this method to create the XML files in the first place and it seems to work fine:
public static void WriteToXmlFile<T>(string filePath, T objectToWrite) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof (T));
writer = new StreamWriter(filePath);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
{
writer.Close();
}
}
}
It gets me an XML file that looks like this:
<RootObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Services>
<TileMapService>
<Title>Some title</Title>
<href>http://something</href>
</TileMapService>
</Services>
</RootObject>
Your code works fine. The "There is an error in XML document (2, 2)." might be because your actual file (not the one created by WriteToXmlFile<T>) has whitespace at the start, or is using the wrong namespace. Check the .InnerException for more detail, or (perhaps simpler) please post the actual xml file contents. Example of it working fine (along with some recommended tweaks to the two key methods):
static void Main()
{
RootObject obj = new RootObject
{
Services = new Services
{
TileMapService = new Service
{
Title = "abc",
href = "def"
}
}
};
WriteToXmlFile("foo.xml", obj);
var loaded = Deserialize<RootObject>("foo.xml");
var svc = loaded.Services.TileMapService;
System.Console.WriteLine(svc.Title); // abc
System.Console.WriteLine(svc.href); // def
}
public static void WriteToXmlFile<T>(string filePath, T objectToWrite)
{
var serializer = new XmlSerializer(typeof(T));
using (var writer = new StreamWriter(filePath))
{
serializer.Serialize(writer, objectToWrite);
}
}
public static T Deserialize<T>(string filePath)
{
var serializer = new XmlSerializer(typeof(T));
using (var reader = new StreamReader(filePath))
{
return (T)serializer.Deserialize(reader);
}
}

PaymentDetails is not successfully deserialized, returning a null object, because it seems it is expected to have IXmlDeserializable

[XmlRoot("Quote")]
public class Quote
{
[XmlElement("Insurance")]
public InsuranceDetails InsDetails { get; set; }
[XmlElement("Payment")]
public PaymentDetails PayDetails { get; set; }
}
public class InsuranceDetails : IXmlSerializable
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement("Insurance");
Details1 = reader.ReadElementString("Details1");
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
// do write suff
}
}
public class PaymentDetails
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
}
Given this example, using XmlSerializer to deserialize my string to QuoteObject, PaymentDetails is not successfully deserialized, returning a null object, because it seems it is expected to have IXmlDeserializable. It only works if PaymentDetails is parsed in first place. Is this some expected behavior from XmlSerializer?
using (TextReader read = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(Quote));
return (Quote)serializer.Deserialize(read);
}
Well these are the ReadXml and WriteXml I modified:
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
var empty=reader.IsEmptyElement;
reader.ReadStartElement();
if(!empty){
Details1=reader.ReadElementString("Details1");
reader.ReadEndElement();
}
}
public void WriteXml(XmlWriter writer)
{
var str=string.IsNullOrWhiteSpace(Details1)?"":Details1;
writer.WriteElementString("Details1",str);
}
Following are serialize and deserialize functions:
public static string Serialize<T>(T t)
{
var xmlser=new XmlSerializer(typeof(T));
XmlWriterSettings settings = new XmlWriterSettings();
using(StringWriter textWriter = new StringWriter()) {
using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
xmlser.Serialize(xmlWriter, t);
}
return textWriter.ToString();
}
}
public static T Deserialize<T>(string xml)
{
if(string.IsNullOrEmpty(xml)) {
return default(T);
}
XmlSerializer serializer = new XmlSerializer(typeof(T));
XmlReaderSettings settings = new XmlReaderSettings();
using(StringReader textReader = new StringReader(xml)) {
using(XmlReader xmlReader = XmlReader.Create(textReader, settings)) {
return (T) serializer.Deserialize(xmlReader);
}
}
}
Serialization Test:
var q=new Quote();
q.PayDetails = new PaymentDetails{Details1="Payment Details 1"};
q.InsDetails=new InsuranceDetails{Details1="Insurance Details 1"};
str = Serialize<Quote>(q);
Which gives (str):
<?xml version="1.0" encoding="utf-16"?>
<Quote xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Payment>
<Details1>Payment Details 1</Details1>
</Payment>
<Insurance>
<Details1>Insurance Details 1</Details1>
</Insurance>
</Quote>
Deserialization Test:
var dq=Deserialize<Quote>(str);
Console.WriteLine(dq.PaymentDetails.Detail1);//gives "Payment Details 1"
Console.WriteLine(dq.InsuranceDetails.Detail1);//gives "Insurance Details 1"
PS:- The Serialize code was copied from another SO answer verbatim. I learned how to serialize to string using StringWriter.
First of all you don't have to implement IXmlSerializable in any of the classes. Second of all, you don't provide the content of the xml variable. It may contain a mistype/bug, if you created it manually.
I used the following code, to test your classes:
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace XmlDeSerialize
{
[XmlRoot("Quote")]
public class Quote
{
[XmlElement("Insurance")]
public InsuranceDetails InsDetails { get; set; }
[XmlElement("Payment")]
public PaymentDetails PayDetails { get; set; }
}
public class InsuranceDetails
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
}
public class PaymentDetails
{
[XmlElement(ElementName = "Details1")]
public string Details1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var qin = new Quote
{
InsDetails = new InsuranceDetails { Details1 = "insurance details text" },
PayDetails = new PaymentDetails { Details1 = "payment details text" },
};
string xml;
using (var stream = new MemoryStream())
{
var serializer = new XmlSerializer(typeof(Quote));
serializer.Serialize(stream, qin);
stream.Position = 0;
using (var sr = new StreamReader(stream))
{
xml = sr.ReadToEnd();
}
}
Quote qout;
using (TextReader read = new StringReader(xml))
{
var deserializer = new XmlSerializer(typeof(Quote));
var obj = deserializer.Deserialize(read);
qout = (Quote)obj;
}
Console.WriteLine("InsDetails.Details1='{0}'", qout.InsDetails.Details1);
Console.WriteLine("PayDetails.Details1='{0}'", qout.PayDetails.Details1);
}
}
}
The value of xml after serialization:
<?xml version="1.0"?>
<Quote xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Insurance>
<Details1>insurance details text</Details1>
</Insurance>
<Payment>
<Details1>payment details text</Details1>
</Payment>
</Quote>
The console output I received:
InsDetails.Details1='insurance details text'
PayDetails.Details1='payment details text'
Try the code yourself and see if it works for you. Clearly to me you don't provide valid XML content for deserialization, or other part of your code you did not provide in your question is to blame.

Deserialize a restful uri

I'm trying to deserialize a rest uri located at http://ws.geonames.org/countryInfo?lang=it&country=DE and keep getting error (There is an error in XML document (1, 1)). Plug http://ws.geonames.org/countryInfo?lang=it&country=DE into the browser and you can see the result.
I have a class
public class Country
{
public string CountryName {get;set;}
public string CountryCode {get;set;}
}
and the method in my console app is as follows:
static void DeserializeTheXML()
{
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "countryName";
xRoot.IsNullable = true;
XmlSerializer ser = new XmlSerializer(typeof(Country), xRoot);
XmlReader xRdr = XmlReader.Create(new StringReader("http://ws.geonames.org/countryInfo?lang=it&country=DE"));
Country tvd = new Country();
tvd = (Country)ser.Deserialize(xRdr);
Console.WriteLine("Country Name = " + tvd.CountryName);
Console.ReadKey();
}
any ideas on how to deserialize this rest service? thanks..
For serialization to work successfully you need to decorate your objects with the proper serialization attributes or use the XmlAttributeOverrides constructor. Also don't forget that XML is case sensitive and your objects must reflect the XML structure you are deserializing:
public class GeoNames
{
[XmlElement("country")]
public Country[] Countries { get; set; }
}
public class Country
{
[XmlElement("countryName")]
public string CountryName { get; set; }
[XmlElement("countryCode")]
public string CountryCode { get; set; }
}
class Program
{
static void Main()
{
var url = "http://ws.geonames.org/countryInfo?lang=it&country=DE";
var serializer = new XmlSerializer(typeof(GeoNames), new XmlRootAttribute("geonames"));
using (var client = new WebClient())
using (var stream = client.OpenRead(url))
{
var geoNames = (GeoNames)serializer.Deserialize(stream);
foreach (var country in geoNames.Countries)
{
Console.WriteLine(
"code: {0}, name: {1}",
country.CountryCode,
country.CountryName
);
}
}
}
}

Categories