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.
Related
I'm pretty new to programming , I still have a lot to learn and I would need a little help please :) !
I saw in other posts the same error but I could not solve anything even with those explanations
The error i get
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JSON_TEST2.Class1+weatherinfo' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'weather', line 1, position 45.'
I have this class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
namespace JSON_TEST2
{
public class Class1
{
public class coord
{
public double lat { get; set; }
public double lon { get; set; }
}
public class weatherinfo
{
public string[] weather { get; set; }
}
public class WeatherMain
{
public coord coord { get; set; }
public weatherinfo weather { get; set; }
public void display()
{
Console.WriteLine("lon: {0}", this.coord.lon);
Console.WriteLine("lat: {0}", this.coord.lat);
Console.WriteLine("id: {0}", this.weather.weather);
}
}
}
}
I deserialize with this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net;
namespace JSON_TEST2
{
class Program
{
static void Main()
{
WebClient wc = new WebClient();
var json = wc.DownloadString(#"http://api.openweathermap.org/data/2.5/weather?q=Bucharest,ro&APPID=829b7bfc0558b9e501f43fc6087fca3a");
Console.WriteLine(json);
Class1.WeatherMain vreme = JsonConvert.DeserializeObject <Class1.WeatherMain>(json);
vreme.display();
Console.ReadLine();
}
}
}
This is the JSON I get from the server:
{
"coord":{
"lon":26.1,
"lat":44.44
},
"weather":[
{
"id":804,
"main":"Clouds",
"description":"overcast clouds",
"icon":"04n"
}
],
"base":"stations",
"main":{
"temp":287.64,
"pressure":1012,
"humidity":87,
"temp_min":287.15,
"temp_max":288.15
},
"visibility":8000,
"wind":{
"speed":2.6,
"deg":50
},
"clouds":{
"all":100
},
"dt":1573682313,
"sys":{
"type":1,
"id":6911,
"country":"RO",
"sunrise":1573708189,
"sunset":1573743018
},
"timezone":7200,
"id":683506,
"name":"Bucharest",
"cod":200
}
As described in comments, your classes doesn't match the Json.This is because the weather itself is an array, and not an object.
"weather":[
{
"id":804,
"main":"Clouds",
"description":"overcast clouds",
"icon":"04n"
}
]
You need to alter the weatherinfo and WeatherMain as following.
public class weatherinfo
{
public int id { get; set; }
public string main { get; set; }
public string description { get; set; }
public string icon { get; set; }
}
public class WeatherMain
{
public coord coord { get; set; }
public List<weatherinfo> weather { get; set; }
public void display()
{
Console.WriteLine("lon: {0}", this.coord.lon);
Console.WriteLine("lat: {0}", this.coord.lat);
Console.WriteLine("id: {0}", string.Join(Environment.NewLine,this.weather.Select(c=>$"Weather:{c.main},Description:{c.description}")));
}
}
Demo Code
I am trying to stream a large JSON file and deserialize item by item during the streaming.
I am using for this test https://github.com/ysharplanguage/FastJsonParser/blob/master/JsonTest/TestData/fathers.json.txt.
This is my code:
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
namespace AMServices.Controllers
{
public class FathersData
{
public Father[] fathers { get; set; }
}
public class Someone
{
public string name { get; set; }
}
public class Father : Someone
{
public int id { get; set; }
public bool married { get; set; }
// Lists...
public List<Son> sons { get; set; }
// ... or arrays for collections, that's fine:
public Daughter[] daughters { get; set; }
}
public class Child : Someone
{
public int age { get; set; }
}
public class Son : Child
{
}
public class Daughter : Child
{
public string maidenName { get; set; }
}
public class StreamerController : ApiController
{
static readonly JsonSerializer _serializer = new JsonSerializer();
static readonly HttpClient _client = new HttpClient();
[HttpPost]
[Route("streamer/stream")]
public async Task<IHttpActionResult> stream()
{
string apiUrl = "https://github.com/ysharplanguage/FastJsonParser/blob/master/JsonTest/TestData/fathers.json.txt";
using (var stream = await _client.GetStreamAsync(apiUrl).ConfigureAwait(false))
using (var reader = new StreamReader(stream))
using (var json = new JsonTextReader(reader))
{
if (json == null)
StatusCode(HttpStatusCode.InternalServerError);
JsonSerializer serializer = new JsonSerializer();
JObject obj = JObject.Load(json);
// Father f = serializer.Deserialize<Father>(json);
}
return StatusCode(HttpStatusCode.OK);
}
}
}
When i call this WebAPI Controller Method from Postman i get the following error
"ExceptionMessage": "Unexpected character encountered while parsing value: <. Path '', line 0, position 0.",
"ExceptionType": "Newtonsoft.Json.JsonReaderException",
What is wrong with this code?
You are trying to parse an html page.
Try with the raw version :
https://raw.githubusercontent.com/ysharplanguage/FastJsonParser/master/JsonTest/TestData/fathers.json.txt
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( ){}
I would like to deserialize the following XML into the following type. How do I map the status correctly? (it is currently not mapped and remains null after the deserialization process)
<?xml version="1.0" encoding="UTF-8"?>
<job:job-status xsi:schemaLocation="http://marklogic.com/xdmp/job-status job-status.xsd" xmlns:job="http://marklogic.com/xdmp/job-status" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<job:forest>
<job:forest-name>FOREST2</job:forest-name>
<job:forest-id>1168048654236455340</job:forest-id>
<job:status>completed</job:status>
<job:journal-archiving>false</job:journal-archiving>
</job:forest>
</job:job-status>
[XmlRoot("job-status", Namespace = "http://marklogic.com/xdmp/job-status")]
public class DatabaseRestoreStatus
{
[XmlElement("status")]
public string Status { get; set; }
}
Using DataContract Serializer worked for me. I also had to create one more class.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
namespace SandboxConoleApp
{
internal class Program
{
private static void Main(string[] args)
{
DatabaseRestoreStatus data = null;
using (var stream = File.Open("test.xml",FileMode.Open))
{
var formatter = new DataContractSerializer(typeof(DatabaseRestoreStatus));
data = (DatabaseRestoreStatus)formatter.ReadObject(stream);
}
}
}
[DataContract(Name = "job-status", Namespace = "http://marklogic.com/xdmp/job-status")]
public class DatabaseRestoreStatus
{
[DataMember(Name = "forest")]
public Forest Forest { get; set; }
}
[DataContract(Name = "forest", Namespace = "http://marklogic.com/xdmp/job-status")]
public class Forest
{
[DataMember(Name = "status")]
public string Status { get; set; }
}
}
I want to add at the top of my xml file some notes for the user who reads it. I am not sure how to do this though with xml serialization.
I was looking at this post
C# XML Insert comment into XML after xml tag
XDocument document = new XDocument();
document.Add(new XComment("Product XY Version 1.0.0.0"));
using (var writer = document.CreateWriter())
{
serializer.WriteObject(writer, graph);
}
document.Save(Console.Out);
but I am not really sure what is going on and how to add this to my code. Basically I just have some classes that I serialize into xml and stick it in a memory stream.
So I am not sure at what point I should add the comments into.
Thanks
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
[XmlRoot("Course")]
public class MyWrapper
{
public MyWrapper()
{
TaskList = new List<Tasks>();
}
[XmlElement("courseName")]
public string CourseName { get; set; }
[XmlElement("backgroundColor")]
public string BackgroundColor { get; set; }
[XmlElement("fontColor")]
public string FontColor { get; set; }
[XmlElement("sharingKey")]
public Guid SharingKey { get; set; }
[XmlElement("task")]
public List<Tasks> TaskList { get; set; }
}
public class Tasks
{
[XmlAttribute("type")]
public string Type { get; set; }
[XmlElement("taskName")]
public string TaskName { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("taskDueDate")]
public DateTime TaskDueDate { get; set; }
[XmlElement("weight")]
public decimal? Weight { get; set; }
[XmlElement("beforeDueDateNotification")]
public int BeforeDueDateNotification { get; set; }
[XmlElement("outOf")]
public decimal? OutOf { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyWrapper wrap = new MyWrapper();
wrap.CourseName = "Comp 1510";
wrap.FontColor = "#ffffff";
wrap.BackgroundColor = "#ffffff";
wrap.SharingKey = Guid.NewGuid();
Tasks task = new Tasks()
{
TaskName = "First Task",
Type = "Assignment",
TaskDueDate = DateTime.Now,
Description = "description",
BeforeDueDateNotification = 30,
OutOf = 50.4M
};
wrap.TaskList.Add(task);
var stream = SerializeToXML(wrap);
}
static public MemoryStream SerializeToXML(MyWrapper list)
{
XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
MemoryStream stream = new MemoryStream();
serializer.Serialize(stream, course);
return stream;
}
}
}
Just put an XmlWriter as an intermediate level between the MemoryStream and the XmlSerializer:
static public MemoryStream SerializeToXML(MyWrapper list)
{
XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
writer.WriteStartDocument();
writer.WriteComment("Product XY Version 1.0.0.0");
serializer.Serialize(writer, course);
writer.WriteEndDocument();
writer.Flush();
return stream;
}
Your can add any XML before and after the serialized object graph (as long as the result is valid XML).