I'm trying to parse a JSON file when someone clicks on a button, which replaces the button's Content with data from the JSON.
Currently I'm facing an issue where the data remains null. The code is as follows:
private void Button1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Button1.FontSize = 15;
Button1.Content = "Fetching...";
var client = new WebClient();
client.OpenReadCompleted +=
(s, eargs) =>
{
var serializer = new DataContractJsonSerializer(typeof(RadioRootObject));
if (eargs.Error != null)
{
if (eargs.Error.Message.Contains("NotFound"))
{
MessageBox.Show("Could not retrieve playlist", "Error", MessageBoxButton.OK);
Button1.Content = "Could not retrieve playlist";
}
else
{
MessageBox.Show("Could not retrieve playlist", "Error", MessageBoxButton.OK);
Button1.Content = "Could not retrieve playlist";
}
}
else
{
var root = (RadioRootObject)serializer.ReadObject(eargs.Result);
var songHistory = root.station3;
Button1.Content = songHistory.text;
}
};
var uri = new Uri("http://www.reignofcomputer.com/tmpsend/nowplaying.json");
client.OpenReadAsync(uri);
}
public class station1
{
public string station { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string text { get; set; }
}
public class station2
{
public string station { get; set; }
public int listeners { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string text { get; set; }
}
public class station3
{
public string station { get; set; }
public int listeners { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string text { get; set; }
}
public class RadioRootObject
{
public station1 station1 { get; set; }
public station2 station2 { get; set; }
public station3 station3 { get; set; }
}
root and songHistory remain null and thus throws a NullReferenceException.
station1 and station2 are used in Button2_Tap and Button3_Tap, not shown in the above code, which are similar to Button1_Tap above.
I'm told that the DataContractJsonSerializer cannot match property "1" from the json object to the property station1 on the RadioRootObject class, but I'm not sure how go about making it match.
I am unable to alter the data in the JSON itself. Any ideas?
Check this blog post for how to Parsing JSON in a Windows Phone Application
And accordingly, try this
private void Button_Click(object sender, RoutedEventArgs e)
{
Button1.FontSize = 15;
Button1.Content = "Fetching...";var client = new WebClient();
var uri = new Uri("http://www.reignofcomputer.com/tmpsend/nowplaying.json");
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(uri);
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var jobj = JObject.Parse(e.Result);
var station3 = jobj["3"];
Button1.Content = station3["text"];
}
Since the property in the JSON is "1" and the name of the member of RadioRootObject is "station1", these don't match. You can tell the serializer what the name in JSON is by using a DataMemberAttribute, something like
public class RadioRootObject
{
[DataMember(Name="1")]
public station1 station1 { get; set; }
[DataMember(Name="2")]
public station2 station2 { get; set; }
[DataMember(Name="3")]
public station3 station3 { get; set; }
}
Honestly, I thought you had to have [DataContract] and [DataMember] attributes on your class and members anyway (see the example for DataContractJsonSerializer), but I could be wrong :-)
Related
I'm getting an empty object when I try to Deserialize a OneNote GetAllNotebooks query.
string[] tempCapture = null;
var url = new Uri("https://graph.microsoft.com/v1.0/me/onenote/notebooks");
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (IsAuthenticated)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
}
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
tbResponse.Text = result.ToString();
DataContractJsonSerializer ser1 = new DataContractJsonSerializer(typeof(List<Value>));
MemoryStream stream1 = new MemoryStream(Encoding.UTF8.GetBytes(tbResponse.Text.ToString()));
var obj1 = (List<Value>)ser1.ReadObject(stream1);
I'm trying to get a list of notebooks, names, links to add to a database. And my table structure matches the class below.
Here is my OneNote API class
public class Value
{
public bool isDefault { get; set; }
public string userRole { get; set; }
public bool isShared { get; set; }
public string sectionsUrl { get; set; }
public string sectionGroupsUrl { get; set; }
public Links links { get; set; }
public string name { get; set; }
public string self { get; set; }
public string createdBy { get; set; }
public string lastModifiedBy { get; set; }
public string lastModifiedTime { get; set; }
public string id { get; set; }
public string createdTime { get; set; }
}
Here is my new code with the RootObject. I'm still getting an error. It is in the catch exception.
var test = await client.GetAsync(url);
string testStr = await test.Content.ReadAsStringAsync();
DataContractJsonSerializer serial = new DataContractJsonSerializer(typeof(RootObject));
MemoryStream testStream = new MemoryStream(Encoding.UTF8.GetBytes(testStr));
try
{
var objx = (List<RootObject>)serial.ReadObject(testStream);
}
catch(Exception ex)
{
ex.ToString();
//"There was an error deserializing the object of type OneNoteSOAP2.RootObject. End element 'createdBy' from namespace '' expected. Found element 'user' from namespace ''."
}
You can use http://json2csharp.com/. Basically, just copy the value of our JSON being returned, and use the classes generated by this website. Use RootObject to deserialize.
I ran this for you and obtained these classes:
public class OneNoteClientUrl
{
public string href { get; set; }
}
public class OneNoteWebUrl
{
public string href { get; set; }
}
public class Links
{
public OneNoteClientUrl oneNoteClientUrl { get; set; }
public OneNoteWebUrl oneNoteWebUrl { get; set; }
}
public class Value
{
public string id { get; set; }
public string self { get; set; }
public string createdTime { get; set; }
public string name { get; set; }
public string createdBy { get; set; }
public string lastModifiedBy { get; set; }
public string lastModifiedTime { get; set; }
public bool isDefault { get; set; }
public string userRole { get; set; }
public bool isShared { get; set; }
public string sectionsUrl { get; set; }
public string sectionGroupsUrl { get; set; }
public Links links { get; set; }
}
public class RootObject
{
public List<Value> value { get; set; }
}
I am able to draw the polyline on the map on the area that I have tapped on by the MapGesture event, however I would like to display the polyline based on my JSON data. Is there anybody that can give me some guidance how I can code it? Thank you!
public MainPage()
{
InitializeComponent();
Draw MyDrawObject = new Draw(MyMap)
{
FillSymbol = LayoutRoot.Resources["RedFillSymbol"] as FillSymbol
};
MyDrawObject.DrawComplete += MyDrawObject_DrawComplete;
MyDrawObject.DrawMode = DrawMode.Polyline;
MyDrawObject.IsEnabled = true;
// Create webclient.
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("http://www.onemap.sg/publictransportation/service1.svc/routesolns?token=qo/s2TnSUmfLz+32CvLC4RMVkzEFYjxqyti1KhByvEacEdMWBpCuSSQ+IFRT84QjGPBCuz/cBom8PfSm3GjEsGc8PkdEEOEr&sl=530927&el=569830&startstop=&endstop=&walkdist=300&mode=bus&routeopt=cheapest&retgeo=true&maxsolns=1&callback="));
}
private void MyDrawObject_DrawComplete(object sender, ESRI.ArcGIS.Client.DrawEventArgs args)
{
Graphic graphic = new Graphic()
{
Geometry = args.Geometry,
Symbol = LayoutRoot.Resources["RedFillSymbol"] as FillSymbol
};
GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
graphicsLayer.Graphics.Add(graphic);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//base.OnNavigatedTo(e);
setUpLayers();
}
private void setUpLayers()
{
ArcGISTiledMapServiceLayer baseMapLayer = new ArcGISTiledMapServiceLayer();
baseMapLayer.ID = "BaseMap";
baseMapLayer.Url = "http://e1.onemap.sg/arcgis/rest/services/SM128/MapServer";
MyMap.Layers.Add(baseMapLayer);
}
public class STEP
{
//public string STEP { get; set; }
public string type { get; set; }
public string ServiceType { get; set; }
public string ServiceID { get; set; }
public string NumberOfStop { get; set; }
public string BoardId { get; set; }
public string BoardDesc { get; set; }
public string BoardDist { get; set; }
public string AlightId { get; set; }
public string AlightDesc { get; set; }
public string AlightDist { get; set; }
}
public class BusRoute
{
public string Solution { get; set; }
public string Duration { get; set; }
public string TotalCard { get; set; }
public string TotalCash { get; set; }
public string TotalDistance { get; set; }
public List<STEP> STEPS { get; set; }
public string TotalStops { get; set; }
public List<List<string>> PATH { get; set; }
}
public class RootObject
{
public List<BusRoute> BusRoute { get; set; }
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
foreach (var route in rootObject.BusRoute)
{
string duration = route.Duration;
string totalStops = route.TotalStops;
//tb_test.Text = "Total Duration: " + duration;
//tb_test2.Text = "Total number of stops: " + totalStops;
}
}
private void MyMap_MapGesture(object sender, ESRI.ArcGIS.Client.Map.MapGestureEventArgs e)
{
if(e.Gesture == GestureType.Tap)
{
MapPoint point = new MapPoint(e.MapPoint.X,e.MapPoint.Y);
double x = point.X;
double y = point.Y;
var _polyline = new MapPolyline();
_polyline.StrokeColor = Colors.Blue;
_polyline.StrokeThickness = 2;
_polyline.Path.Add(new GeoCoordinate(x,y));
}
}
}
You would need to have a webapi (or any service) endpoint to connect to and retrieve the data. Once you get the data you will need to convert the DataTransfer Object into a GeoCoordinate object so that it can be added to the map:
MapPolyline line = new MapPolyline();
public void InsertCoordsToMap(IEnumerable<YourDtoClass> deSerializedJson) {
foreach(var item in deSerializedJson) {
GeoCoordinate elementToAdd = new GeoCoordinate(item.Latidude, item.Longitude);
map.Path.Add(elementToAdd);
}
}
I am unable to deserialize my Json String with the help of "DataContractJsonSerializer". I can't use third party tool for deserialization, my json string has no any enter code hereMainObject so i am unable to do, Please help me. My json data is below.
[{
"id": "2348",
"fo": "",
"na": "og",
"ex": "",
"ge": "",
"no_cl": "Phr",
"wo_cl": {
"id": "27",
"na": "kon",
"na_cl": "WordClass"
},
"con": []
}]
my classes according to above Json is following.
public class WoCl
{
public string id { get; set; }
public string na { get; set; }
public string na_cl { get; set; }
}
public class RootObject
{
public string id { get; set; }
public string fo { get; set; }
public string na { get; set; }
public string ex { get; set; }
public string ge { get; set; }
public string no_cl { get; set; }
public WoCl wo_cl { get; set; }
public List<object> con { get; set; }
}
My deserializing code is following.
string json = returnDictionaryJsonFromServer();//this function returning above json data
List<MainObject> obj = new List<MainObject>();
var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json));
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = serializer.ReadObject(memoryStream) as List<MainObject>;
return obj;
public AllAnnotatedData Deserializer(string json)
{
MyWrapper obj = new MyWrapper();
using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
try
{
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (MyWrapper)serializer.ReadObject(memoryStream);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return obj;
}
//MyWrapper is following.
[DataContract]
public class MyWrapper
{
[DataMember(Name = "objects")]
public List<mySecondWrapper> mySecondWrapper //this is list of my wrapper class.
{ get; set; }
[DataMember(Name = "property1")]
public Meta AllAnnotationMeta
{ get; set; }
[DataMember(Name = "property2")]
public List<myThirdWrapper> myThirdWrapper //this is list of my wrapper class.
{ get; set; }
}
I have been working on this for some time, i can read the last part, so everything from the square bracket to the end. But i can't read anything before that, when i put it in i Get a NullExceptionReference.
Here's the code I have got:
namespace WP7_ConsumeJSON
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
myButton.Click += new RoutedEventHandler(myButton_Click);
}
void myButton_Click(object sender, RoutedEventArgs e)
{
try
{
WebClient webClient = new WebClient();
Uri uri = new Uri("http://www.ournu.co.uk/list.txt");
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser = new DataContractJsonSerializer(typeof(ObservableCollection<Employee>));
ObservableCollection<Employee> employees = ser.ReadObject(e.Result) as ObservableCollection<Employee>;
foreach (Employee em in employees)
{
string id = em.ServiceName;
string dt = em.Destination;
string tm = em.DepartureTimeAsString;
listBoxService.Items.Add(id);
listBoxDestination.Items.Add(dt);
listBoxTime.Items.Add(tm);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
This is the feed result
{
"StopName":"Race Hill",
"stopId":7553,
"NaptanCode":"bridwja",
"LongName":"Race Hill",
"OperatorsCode1":"07645",
"OperatorsCode2":"7645",
"OperatorsCode3":"50701",
"OperatorsCode4":"bridwja",
"Departures":[
{
"ServiceName":"22",
"Destination":"Churchill Sq",
"DepartureTimeAsString":"1 min",
"DepartureTime":"01/01/0001 00:00:00",
"Notes":""
}
,
{
"ServiceName":"37",
"Destination":"Bristol Estate",
"DepartureTimeAsString":"1 min",
"DepartureTime":"01/01/0001 00:00:00",
"Notes":""
}
]}
So what do i need to do modify in the code in order for me to be able to read the first part of the code.
{
"StopName":"Race Hill",
"stopId":7553,
"NaptanCode":"bridwja",
"LongName":"Race Hill",
"OperatorsCode1":"07645",
"OperatorsCode2":"7645",
"OperatorsCode3":"50701",
"OperatorsCode4":"bridwja",
"Departures":[
Structure of the employee class:
namespace WP7_ConsumeJSON
{
public class Employee
{
public string StopName { get; set; }
public int stopId { get; set; }
public string NaptanCode { get; set; }
public string LongName { get; set; }
public string OperatorsCode1 { get; set; }
public string OperatorsCode2 { get; set; }
public string OperatorsCode3 { get; set; }
public string OperatorsCode4 { get; set; }
public string ServiceName { get; set; }
public string Destination { get; set; }
public string DepartureTimeAsString { get; set; }
public string DepartureTime { get; set; }
public string Notes { get; set; }
}
}
Download project - WP7_JSON.zip
You need to have a container class for the ObservableCollection<Employee> as to gather all that data!
public class RootContainer
{
[DataMember]
public string StopName { get; set; }
[DataMember]
public int stopId { get; set; }
[DataMember]
public string NaptanCode { get; set; }
//Other root properties go here
[DataMember]
public ObservableCollection<Employee> Employees { get; set; }
}
Then change the code like this:
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser = new DataContractJsonSerializer(typeof(RootContainer));
RootContainer rootContainer = ser.ReadObject(e.Result) as RootContainer;
foreach (Employee em in rootContainer.Employees)
{
string id = em.ServiceName;
string dt = em.Destination;
string tm = em.DepartureTimeAsString;
listBoxService.Items.Add(id);
listBoxDestination.Items.Add(dt);
listBoxTime.Items.Add(tm);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
(I wrote the changes with Nodepad, hope I didn't make any error...)
I want to parse a complex JSON on WP7. First I have to parse a JSON feed and I retrieve data to parse second JSON feed.
To parse the first feed I use this web service
http://horaires-ter-sncf.naholyr.fr/prochainsdeparts.php?gare=...
after that we use the code and the station's name to parse the second feed
http://horaires-ter-sncf.naholyr.fr/prochainsdeparts.php?gare=....&id=...
This my code but it doesn't work:
public static class Parser
{
public static string resultats;
public static reponse[] obj = new reponse[]{new reponse(),new reponse()};
public static reponse1 obj1 = new reponse1();
public static void HttpsCompleted_reponse(object sender, DownloadStringCompletedEventArgs e)
{
Horaire hre =new Horaire();
try
{
var ms = new MemoryStream(Encoding.Unicode.GetBytes(resultats));
var ser = new DataContractJsonSerializer(typeof(reponse1));
obj1 = (reponse1)ser.ReadObject(ms);
}
catch
{
WebClient wc = new WebClient();
//wc.DownloadStringCompleted += HttpsCompleted_reponse1;
wc.DownloadStringAsync(new Uri("http://horaires-ter-sncf.naholyr.fr/prochainsdeparts.php?gare=" +hre.gettxt()));
Debug.WriteLine("youuuuuuuuuuuuuuuuuuuuuuuppppppppppiiii");
}
}
/*
public static void HttpsCompleted_reponse1(object sender, DownloadStringCompletedEventArgs e)
{
try
{
var ms = new MemoryStream(Encoding.Unicode.GetBytes(resultats));
var ser = new DataContractJsonSerializer(typeof(Gare));
obj1 = (reponse1)ser.ReadObject(ms);
}
catch
{
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted_reponse;
wc.DownloadStringAsync(new Uri("http://horaires-ter-sncf.naholyr.fr/prochainsdeparts.php?gare=" + obj.success.Gares.Eleme + "&id=" + obj.success.id));
}
}
*/
}
public class Depart
{
[DataMember(Name = "type")]
public string type { get; set; }
[DataMember(Name = "heure")]
public string heure { get; set; }
[DataMember(Name = "destination")]
public string destination { get; set; }
[DataMember(Name="attention")]
public string attention { get; set; }
[DataMember(Name = "retards")]
public string [] retards { get; set; }
[DataMember(Name = "source")]
public string source { get; set; }
public Depart()
{
}
}
public class Success {
[DataMember(Name = "nom")]
public string nom { get; set; }
[DataMember(Name = "id")]
public int id { get; set; }
[DataMember(Name = "departs")]
public Depart[] departs { get; set; }
public Success()
{
this.departs = new Depart[0];
}
}
public class Success1
{
[DataMember(Name="Gares")]
public Gare[] Gares { get; set; }
public Success1()
{
this.Gares = new Gare[0];
}
}
public class Gare{
[DataMember(Name="Nom")]
public string Nom { get; set; }
[DataMember(Name="code")]
public int code { get; set; }
public Gare()
{
}
}
public class reponse
{
[DataMember(Name = "code")]
public string code{get;set;}
[DataMember(Name = "success")]
public Success1 success{get;set;}
public reponse()
{
this.success = new Success1();
}
}
public class reponse1 {
[DataMember(Name = "code")]
public string code { get; set; }
[DataMember(Name = "success")]
public Success success { get; set; }
public reponse1()
{
this.success = new Success();
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
//for (int i=0; i<=Parser.obj1.Length;i++)
Debug.WriteLine(Parser.obj1.success.nom);
}
}
There are several problems in your code. But even if you solved them you wouldn't be able to parse the list of received stations with DataContractJsonSerializer out of the box.
Explanation:
The web site offering the web service you are using says a response from your first "JSON feed" looks like this:
{"code":201,"success":{"gares":{"villefranche-d''alb.-ce":1750,"villefranche
de rgue-12":1749,...}}}
Have a look at the stations and their IDs:
{"villefranche-d''alb.-ce":1750,"villefranche de rgue-12":1749,...}
This is an associative array where the keys and values are not explicitly decorated with "Key" and "Value". But these decorations are necessary for DataContractJsonSerializer to parse the JSON. They would have to be in format
[{“Key”:“villefranche-d''alb.-ce”,“Value”:“1750”},{“Key”:“villefranche
de rgue-12”,“Value”:“1749”}]
to be properly parsed by DataContractJsonSerializer. (The reason is that this serializer supports more complex types than int and string to be used as keys and values.)
This blog post contains a very good description of the matter and how JavaScriptSerializer could be the solution. But unfortunately this class isn't available in Silverlight.
More people having similar problems like you:
Deserialization problem with DataContractJsonSerializer
.NET: Can I use DataContractJsonSerializer to serialize to a JSON associative array?
https://json.codeplex.com/discussions/258083
https://connect.microsoft.com/VisualStudio/feedback/details/558686/
Solution:
Use Json.NET.
Have a look at json.NET, it should provide you with linq2json and a simple serialise to object.