This question already has answers here:
Why XML-Serializable class need a parameterless constructor
(5 answers)
Closed 6 years ago.
I'm currently trying to copy (by use of code) a .xml file and have approached it many different ways. This way however seems to be the one I get the most as i have I've it before but to create a console.writeline output. I can't seem to get it to work for a console.out when producing the .xml layout. It gives me the following error
"cannot be serialized because it does not have a parameterless constructor"
please could anyone help me with this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"SmallResults.xml";
static void Main(string[] args)
{
List<BasicEvent> NewBasicEvent = new List<BasicEvent>();
XmlTextReader fileReader = new XmlTextReader("SmallResults.xml");
XmlDocument xml = new XmlDocument();
xml.Load(fileReader);
XmlNodeList BasicEvents = xml.SelectNodes("/HiP-HOPS_Results/FaultTrees/FMEA/Component/Events/BasicEvent");
if (BasicEvents != null)
{
XmlNode[] nodearray = BasicEvents.Cast<XmlNode>().ToArray();
for (int i = 0; i < BasicEvents.Count; i++)
{
NewBasicEvent.Add(new BasicEvent(nodearray[i].FirstChild.NextSibling.InnerText, nodearray[i].FirstChild.NextSibling.NextSibling.InnerText, nodearray[i].FirstChild.NextSibling.NextSibling.InnerText, nodearray[i].FirstChild.NextSibling.NextSibling.NextSibling.InnerText));
new XmlSerializer(typeof(BasicEvent)).Serialize(Console.Out, nodearray );
}
}
}
}
public class FMEA
{
public List<Component> components { get; set; }
}
public class Component
{
public string CompName { get; set; }
public string BasicEventID { get; set; }
public List<BasicEvent> basicevents { get; set; }
}
public class Events
{
}
public class BasicEvent
{
public string BasicEventName { get; set; }
public string BasicEventShortName { get; set; }
public string BasicEventDescription { get; set; }
public string BasicEventUnavalability { get; set; }
public List<Effects> effects { get; set; }
public BasicEvent( string basiceventname, string basiceventshortname, string basiceventdescription, string basiceventunavalability )
{
BasicEventName = basiceventname;
BasicEventShortName = basiceventshortname;
BasicEventDescription = basiceventdescription;
BasicEventUnavalability = basiceventdescription;
}
The message in the exception is quite clear!
Add the default constructor then:
public BasicEvent( ){}
Related
I'm deserialization the results of a request that has the same tag repeated at multiple levels, I have it working but to do so I'm changing the format of the XML before attempting to deserialize it.
I'm not able to edit the source of the XML to change it to only have Diary at one level.
Is there a way to adjust my XML attributes to handle the deserialization without needing to adjust the response?
XML Response
<?xml version="1.0" ?>
<Root>
<DiaryDetails>
<Diary>
<Diary created_user="value1" created_date="value2" long_text="value3" short_text="value4" entry_type="value5" >Value6</Diary>
</Diary>
<Diary>
<Diary created_user="value7" created_date="value8" long_text="value9" short_text="value10" entry_type="value11" >Value12</Diary>
</Diary>
</DiaryDetails>
</Root>
Class definition
[XmlRoot("DiaryDetails")]
public class Diaries : List<Diary> { }
[XmlRoot("Diary")]
public class Diary
{
[XmlAttribute("created_user")]
public string CreatedBy { get; set; }
[XmlAttribute("created_date")]
public string CreatedDate { get; set; }
[XmlAttribute("long_text")]
public string LongText { get; set; }
[XmlAttribute("short_text")]
public string ShortText { get; set; }
[XmlAttribute("entry_type")]
public string Type { get; set; }
}
Deserialization Method
internal T DeserilaiseObject<T>(string response)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
T DeserilaisedObject;
using (TextReader reader = new StringReader(response))
{
DeserilaisedObject = (T)serializer.Deserialize(reader);
}
return DeserilaisedObject;
}
I'm currently handling this with a string replace:
response = response.Replace("<Diary><Diary", "<Diary").Replace("</Diary></Diary>", "</Diary>");
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication40
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Root));
Root root = (Root)serializer.Deserialize(reader);
}
}
[XmlRoot("Root")]
public class Root
{
[XmlArray("DiaryDetails")]
[XmlArrayItem("Diary")]
public List<DiaryMain> diaries { get; set; }
}
public class DiaryMain
{
public Diary Diary { get; set; }
}
[XmlRoot("Diary")]
public class Diary
{
[XmlAttribute("created_user")]
public string CreatedBy { get; set; }
[XmlAttribute("created_date")]
public string CreatedDate { get; set; }
[XmlAttribute("long_text")]
public string LongText { get; set; }
[XmlAttribute("short_text")]
public string ShortText { get; set; }
[XmlAttribute("entry_type")]
public string Type { get; set; }
}
}
Assuming that you are only interested at the attributed Diary elements at the second nesting level you could do this:
// load your xml into a document
var doc = new XmlDocument();
doc.Load("your_xml_file.xml");
// extract the interesting nodes using xpath
var nodes = doc.SelectNodes("//Diary/Diary");
// deserialize the filtered NodeList (yes it's that clunky)
var serializer = new XmlSerializer(typeof(Diary));
var diaries = nodes.Cast<XmlNode>().Select(x => serializer.Deserialize(new XmlNodeReader(x))).Cast<Diary>().ToArray();
I have a database of teas in a file, I make a new instance of the Tea class with properties like Name, Price, Flavor etc for each tea in the database from the file and place each one of the Tea type objects in a List<Tea>.
Now I need to transfer the names of the teas in a ComboBox and I can't figure it out, with a foreach probably, am I right? But how? Please help! I am probably doing something wrong with the class, see my class code (it's in Czech, don't freak out):
class Caj
{
public static string Nazev
{
get;
set;
}
public static string ZemePuvodu
{
get;
set;
}
public static string Detail
{
get;
set;
}
public static string BarvaNalevu
{
get;
set;
}
public static string Chut
{
get;
set;
}
public static int Cena
{
get;
set;
}
public static int DobaLouhovani
{
get;
set;
}
public static int PocetLzicek
{
get;
set;
}
public static string Nalevy
{
get;
set;
}
public static int TeplotaVody
{
get;
set;
}
public Caj(string nazev, string zemePuvodu, string detail, string barvaNalevu, string chut, int cena, int dobaLouhovani, int pocetLzicek, string nalevy, int teplotaVody)
{
Nazev = nazev;
ZemePuvodu = zemePuvodu;
Detail = detail;
BarvaNalevu = barvaNalevu;
Chut = chut;
Cena = cena;
DobaLouhovani = dobaLouhovani;
PocetLzicek = pocetLzicek;
Nalevy = nalevy;
TeplotaVody = teplotaVody;
}
}
And this is my Form code for now:
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace Zika_projekt
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
static string cesta = "databaze.txt";
static int pocetCaju = File.ReadAllLines(cesta).Length;
private static List<Caj> databaze = new List<Caj>();
private void Form1_Load(object sender, EventArgs e)
{
if (File.Exists(cesta))
{
FileStream fs = new FileStream(cesta, FileMode.OpenOrCreate);
StreamReader sr = new StreamReader(fs, Encoding.UTF8);
cbNazevCaje.Items.Clear();
for (int i = 0; i < pocetCaju; i++)
{
for (int j = 1; j < i;)
{
sr.ReadLine();
}
string[] caj = sr.ReadLine().Split(';');
Caj novyCaj = new Caj(caj[0], caj[1], caj[2], caj[3], caj[4], Convert.ToInt32(caj[5]), Convert.ToInt32(caj[6]), Convert.ToInt32(caj[7]), caj[8], Convert.ToInt32(caj[9]));
cbNazevCaje.Items.Add(novyCaj.);
databaze.Add(novyCaj);
}
sr.Close();
fs.Close();
}
}
}
}
You can use DataSource property of the combobox:
cbNazevCaje.DataSource = databaze;
cbNazevCaje.DisplayMember = "Nazev"; // I'm guessing Nazev is Czech for Name?
I have one problem. I want to read JSON data from my local link and put it in an object class. My problem is that the object[] did not fill with data. Here is my code:
This is the serverdata.cs file with my object inside that I want to fill:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace Διαχείριση
{
class serverdata
{
public προμηθευτέςRow[] Rows;
[DataContract(Name = "ΠρομηθευτέςResult")]
public struct προμηθευτέςRow
{
[DataMember(Name = "Κωδικός")]
public int Κωδικός { get; set; }
[DataMember(Name = "Όνομα")]
public string Όνομα { get; set; }
[DataMember(Name = "Επίθετο")]
public string Επίθετο { get; set; }
[DataMember(Name = "Τηλέφωνο")]
public string Τηλέφωνο { get; set; }
[DataMember(Name = "Διεύθυνση")]
public string Διεύθυνση { get; set; }
[DataMember(Name = "Mail")]
public string Mail { get; set; }
[DataMember(Name = "Προϊόντα")]
public string[] Προϊόντα { get; set; }
}
}
}
Then I have the Form.cs that I want to read the JSON data from my local server:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.Serialization.Json;
namespace Διαχείριση
{
public partial class Administator_Form : Form
{
serverdata ServerData;
public Administator_Form()
{
ServerData = new serverdata();
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
WebRequest request = WebRequest.Create(string.Format("mylocallink"));
WebResponse response = request.GetResponse();
Stream stream = request.GetResponse().GetResponseStream();
StreamReader sread = new StreamReader(stream);
//string sLine = sread.ReadLine();
//MessageBox.Show(sLine);
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<serverdata.προμηθευτέςRow>));
var result = (List<serverdata.προμηθευτέςRow>)json.ReadObject(stream);
ServerData.Rows = result.ToArray();
}
}
}
Now if I call for example MessageBox.Show(ServerData.Rows[0].Κωδικός.ToString()); I get an exception:
"An unhandled exception of type 'System.IndexOutOfRangeException' occurred in Project.exe
Additional information: Index was outside the bounds of the array."
So my problem is that result didn't fill ServerData.Rows.
Here is the JSON data:
{
"ΠρομηθευτέςResult": [
{
"Mail": "mail1",
"Όνομα": "name1",
"Διεύθυνση": "address1",
"Επίθετο": "epitheto1",
"Κωδικός": 1,
"Προϊόντα": [
"subproduct1.1",
"subproduct1.2"
],
"Τηλέφωνο": "1111111111"
},
{
"Mail": "mail2",
"Όνομα": "name2",
"Διεύθυνση": "address2",
"Επίθετο": "epitheto2",
"Κωδικός": 2,
"Προϊόντα": [
"subproduct2.1",
"subproduct2.2"
],
"Τηλέφωνο": "2222222222"
}
]
}
The issue is that you are trying to deserialize into a list, but in your JSON the row data is not at the root level--it is inside an object. To fix, you need to deserialize to your serverdata class directly. But first, you will need to make a couple of changes to the attributes:
Mark your serverdata class with [DataContract]
Mark the Rows property inside serverdata with [DataMember(Name = "ΠρομηθευτέςResult")]
Mark the προμηθευτέςRow struct with [DataContract]
Your class should look like this:
[DataContract]
class serverdata
{
[DataMember(Name = "ΠρομηθευτέςResult")]
public προμηθευτέςRow[] Rows { get; set; }
[DataContract]
public struct προμηθευτέςRow
{
[DataMember(Name = "Κωδικός")]
public int Κωδικός { get; set; }
[DataMember(Name = "Όνομα")]
public string Όνομα { get; set; }
[DataMember(Name = "Επίθετο")]
public string Επίθετο { get; set; }
[DataMember(Name = "Τηλέφωνο")]
public string Τηλέφωνο { get; set; }
[DataMember(Name = "Διεύθυνση")]
public string Διεύθυνση { get; set; }
[DataMember(Name = "Mail")]
public string Mail { get; set; }
[DataMember(Name = "Προϊόντα")]
public string[] Προϊόντα { get; set; }
}
}
Then, change your code to deserialize to your serverdata class:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(serverdata));
ServerData = (serverdata)ser.ReadObject(stream);
You can remove this line as it is no longer needed:
ServerData.Rows = result.ToArray();
After these changes you should find that the Rows array is filled correctly.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have created a class and a global variable named as telephoneNumber. This variable is set in a method and used in another method. However this variable returns null. All methods and this global variable in the same class. Please help to understand this problem. Thanks a lot. My class is :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Net.Http;
using Newtonsoft.Json;
using System.Collections;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string telephoneNumber;
private async void GetSingleLocationInfo(string href)
{
var hereNetUrl = string.Format(
href+"&accept=application/json"
);
// get data from HERE.net REST API
var httpClient = new HttpClient();
var hereNetResponse = await httpClient.GetStringAsync(hereNetUrl);
// deseralize JSON from Here.net
using (var tr = new StringReader(hereNetResponse))
using (var jr = new JsonTextReader(tr))
{
var rootObjectResponse = new JsonSerializer().Deserialize<Object>(jr);
String contacts = rootObjectResponse.ToString();
int startIndex = contacts.IndexOf("phone");
if (startIndex != -1)
{
String value = contacts.Substring(startIndex, 50);
telephoneNumber=value.Substring(value.IndexOf("+"));
}
else
{
telephoneNumber="";
}
}
}
private async void GeocodingWin8Query()
{
// build URL for Here.net REST service
string currentgeoLoc = "37.75075,-122.393472";
string queryString = "taxi";
string appID = "dV04O71v5F3f2W"; // MAKE SURE TO GET YOUR OWN from developers.here.net
object appCode = "8QVr5uSXwfcowDrA"; // MAKE SURE TO GET YOUR OWN from developers.here.net
var hereNetUrl = string.Format(
"http://demo.places.nlp.nokia.com/places/v1/discover/search?at={0}&q={1}&app_id={2}&app_code={3}&accept=application/json",
currentgeoLoc, queryString, appID, appCode);
// get data from HERE.net REST API
var httpClient = new HttpClient();
var hereNetResponse = await httpClient.GetStringAsync(hereNetUrl);
// deseralize JSON from Here.net
using (var tr = new StringReader(hereNetResponse))
using (var jr = new JsonTextReader(tr))
{
var rootObjectResponse = new JsonSerializer().Deserialize<RootObject>(jr);
List<Item> items=rootObjectResponse.results.items;
foreach(Item item in items){
string href = item.href;
GetSingleLocationInfo(href);
Console.WriteLine (telephoneNumber);//returns null
}
}
}
private void button1_Click(object sender, EventArgs e)
{
GeocodingWin8Query();
}
}
public class Category
{
public string id { get; set; }
public string title { get; set; }
public string href { get; set; }
public string type { get; set; }
}
public class Item
{
public List<double> position { get; set; }
public int distance { get; set; }
public string title { get; set; }
public Category category { get; set; }
public string icon { get; set; }
public string vicinity { get; set; }
public List<object> having { get; set; }
public string type { get; set; }
public string href { get; set; }
public string id { get; set; }
public double? averageRating { get; set; }
}
public class Context
{
public Location location { get; set; }
public string type { get; set; }
}
public class Search
{
public Context context { get; set; }
}
public class RootObject
{
public Results results { get; set; }
public Search search { get; set; }
}
}
So, where you call GetSingleLocationInfo, you are calling an async method. GetSingleLocationInfo calwill therefore run as far as the await statement then return stright to the caller, before the it httpClient.GetStringAsync(hereNetUrl); has returned.
To fix this, you need to await on your call GetSingleLocationInfo before trying to access the variable.
Since GetSingleLocationInfo is async it will be called asynchronously, so the Console.WriteLine (telephoneNumber); will be called before the GetSingleLocationInfo change it.
I think you should put an await when calling the method.
String.Substring returns NULL when no string found.
It's going to be "returning" null quite simply because telephoneNumber hasn't been set yet.
Your declaration of the variable private string telephoneNumber; doesn't set any value thus it is an empty string or null.
My guess would be your method where you print it out is being called before the method where you actually set telephoneNumber to have a value.
I have this piece of code which is working fine,
My question is if i want to add another element to the xml named 'Allow'. the Allow Element can get the values of 'True' or 'False'. I want to convert it to a boolean property in my Plugin class, meaning the Plugin will have the additional property:
public bool Allow { get; set; }
is there a possibility to convert it?
can you give a code example?
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml.Linq;
using System.Reflection;
using System.Text;
namespace WindowsFormsApplication1
{
public abstract class Plugin
{
public string Type { get; set; }
public string Message { get; set; }
}
public class FilePlugin : Plugin
{
public string Path { get; set; }
}
public class RegsitryPlugin : Plugin
{
public string Key { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
static class MyProgram
{
[STAThread]
static void Main(string[] args)
{
string xmlstr =#"
<Client>
<Plugin Type=""FilePlugin"">
<Message>i am a file plugin</Message>
<Path>c:\</Path>
</Plugin>
<Plugin Type=""RegsitryPlugin"">
<Message>i am a registry plugin</Message>
<Key>HKLM\Software\Microsoft</Key>
<Name>Version</Name>
<Value>3.5</Value>
</Plugin>
</Client>
";
Assembly asm = Assembly.GetExecutingAssembly();
XDocument xDoc = XDocument.Load(new StringReader(xmlstr));
Plugin[] plugins = xDoc.Descendants("Plugin")
.Select(plugin =>
{
string typeName = plugin.Attribute("Type").Value;
var type = asm.GetTypes().Where(t => t.Name == typeName).First();
Plugin p = Activator.CreateInstance(type) as Plugin;
p.Type = typeName;
foreach (var prop in plugin.Descendants())
{
type.GetProperty(prop.Name.LocalName).SetValue(p, prop.Value, null);
}
return p;
}).ToArray();
//
//"plugins" ready to use
//
}
}
}
change
foreach (var prop in plugin.Descendants())
{
type.GetProperty(prop.Name.LocalName).SetValue(p, prop.Value, null);
}
to
foreach (var prop in plugin.Descendants())
{
var pi = type.GetProperty(prop.Name.LocalName);
object newVal = Convert.ChangeType(prop.Value, pi.PropertyType);
pi.SetValue(p, newVal, null);
}
PS:
use <Allow>true</Allow> not <Allow>True</Allow>