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.
Related
hello people I have this Json data:
https://openexchangerates.org/api/latest.json?app_id=6cf59607a32d408eb3e04de1427a3169
and I want to deserialize in the following class
using Newtonsoft.Json;
using System.Collections.Generic;
namespace Divisas2MVVM2.Classes
{
public class ExchangeRates
{
[JsonProperty(PropertyName = "disclaimer")]
public string Disclaimer { get; set; }
[JsonProperty(PropertyName = "license")]
public string License { get; set; }
[JsonProperty(PropertyName = "timestamp")]
public int TimeStamp { get; set; }
[JsonProperty(PropertyName = "base")]
public string Base { get; set; }
[JsonProperty(PropertyName = "rates")]
public Rates Rates { get; set; }
}
public class Rates
{
public double AED { get; set; }
public double AFN { get; set; }
public double ALL { get; set; }
public double AMD { get; set; }
// I cut the text so that it would not be to long
public double ZMW { get; set; }
public double ZWL { get; set; }
}
public class Rate
{
public double TaxRate { get; set; }
public string Code { get; set; }
}
this is my attribute
private ExchangeRates exchangeRates;
the constructor of my MainViewModel
new ObservableCollection data
Rates = new ObservableCollection<Rate>();
and in this method a get the json data
try
{
var client = new HttpClient();
client.BaseAddress = new Uri("https://openexchangerates.org");
var url = "/api/latest.json?app_id=6cf59607a32d408eb3e04de1427a3169";
var response = await client.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
Message = response.StatusCode.ToString();
IsRunning = false;
return;
}
var result = await response.Content.ReadAsStringAsync();
exchangeRates = JsonConvert.DeserializeObject<ExchangeRates>(result);
}
everything works fine, the variable result has correctly the json data in a string format, but when i call JsonConvert . DeserializeObject, the data "rates" it is not assigned correctly, all the other data: disclaimer", "license", "timestamp" etc. is correctly assigned. only rates fail.
the string is correct
other data is correct in the class
rates is incorrect
sorry for my English I hope you have understood me :)
use this as your model class
namespace Rate
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class Rates
{
[JsonProperty("disclaimer")]
public string Disclaimer { get; set; }
[JsonProperty("license")]
public string License { get; set; }
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("rates")]
public Dictionary<string, double> RatesRates { get; set; }
}
public partial class Rates
{
public static Rates FromJson(string json) => JsonConvert.DeserializeObject<Rates>(json, Rate.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this Rates self) => JsonConvert.SerializeObject(self, Rate.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
Then do this in your class
var data = Rate.Rates.FromJson("jsonresult");
var rate = data.RatesRates;
foreach (var pair in rate)
{
string symbol = pair.Key; //"AED"
double value = pair.Value; //3.673175,
}
var time = data.Timestamp;
var disclaimer = data.Disclaimer;
var license = data.License;
Tested and working
I want to show user_id from the following JSON:
[{"username":"Kac26","email":"xklemenx#gmail.com","city":"Slovenj Gradec","id":"15"}]
So I save this JSON to class. I get JSON from my webpage.
My class:
public class Class2
{
public string username{ get; set; }
public string email { get; set; }
public string city { get; set; }
public int id { get; set; }
}
Saving JSON to class:
private async void Login_Tapped(object sender, TappedRoutedEventArgs e)
{
string str = user.Text; //get user name from textbox
HttpClient http = new HttpClient();
var response= await http.GetStringAsync("http://mywebpage.com/events/apis/user.php/user=" + str);
}
Then I want to show user id in textbox_id when i press button.
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
textbox_id.Text = Class2.id;
}
But error shows up when I try to reach Class2.id
Anyone know how to do that? And do I save json to class correct?
Thanks!!!
In "Saving JSON to class", I don't see where you are actually doing that. Here's how you would deserialize the string returned by the service:
private async void Login_Tapped(object sender, TappedRoutedEventArgs e)
{
string str = user.Text; //get user name from textbox
HttpClient http = new HttpClient();
var response = await http.GetStringAsync("http://mywebpage.com/events/apis/user.php/user=" + str);
Class2 myClass2 = null;
try
{
var jsonSerializer = new DataContractJsonSerializer(typeof(Class2));
using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(response)))
{
myClass2 = jsonSerializer.ReadObject(stream) as Class2;
}
}
catch
{
// serialization error occurred
}
// do something with myClass2
}
Also, FYI if you don't want the property names on your response class to match the JSON properties (for example, not be lower case), you can use DataContractAttribute and DataMemberAttribute on your class like so:
[DataContract]
public class Class2
{
[DataMember(name = "username")]
public string UserName { get; set; }
[DataMember(name = "email")]
public string EMail { get; set; }
[DataMember(name = "city")]
public string SomeCompletelyDifferentNameForCity { get; set; }
[DataMember(name = "id")]
public int Id { get; set; }
}
Class2.id is a static access to a non-static property of Class2. You have to create an instance of Class2 with new Class2(); at some point and then you can access the property.
I want to read some List<> of Object from a JSON file, which is generated by a PHP file.
When I try to compile it, I have some problems, it seems that the Smartphone is waiting something. Also I'm not sure if the read is correct for Windows Phone. Thank you in advance for your help !
This is the JSON file example:
{"giocatori":[{"Giocatore":"124","Cognome":"DE SANCTIS","Ruolo":"P","Squadra":"ROM"},{"Giocatore":"140","Cognome":"MIRANTE","Ruolo":"P","Squadra":"PAR"},{"Giocatore":"156","Cognome":"SKORUPSKI","Ruolo":"P","Squadra":"ROM"}],"success":1}
These are the Objects:
public class Giocatori
{
public string Giocatore { get; set; }
public string Cognome { get; set; }
public string Ruolo { get; set; }
public string Squadra { get; set; }
public override string ToString()
{
return Giocatore + " " + Cognome + " " + Ruolo + " " + Squadra;
}
}
public class RootObject
{
public List<Giocatori> giocatori { get; set; }
public int success { get; set; }
}
And here are the methods:
private async Task<RootObject> getPlayers()
{
Uri serviceUri = new Uri("myURL");
HttpClient client = new HttpClient();
string jsonString = await client.GetStringAsync(serviceUri);
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
RootObject RootObject = new RootObject();
DataContractJsonSerializer ser = new DataContractJsonSerializer(RootObject.GetType());
RootObject = ser.ReadObject(ms) as RootObject;
return RootObject;
}
private void loadPlayers()
{
RootObject players = getPlayers().Result;
setComboboxs(players.giocatori); // The method which I need to use the
}
Download JSON.Net package via Nuget.
Right Click project > Manage Nuget > Json.net > Install
According to http://json2csharp.com/ your class should look like this.
public class Giocatori
{
public string Giocatore { get; set; }
public string Cognome { get; set; }
public string Ruolo { get; set; }
public string Squadra { get; set; }
}
public class RootObject
{
public List<Giocatori> giocatori { get; set; }
public int success { get; set; }
}
RootObject can be renamed to whatever you like.
When you receive your JSON do
JsonConvert.DeserializeObject<RootObject>("jsonstring");
how can i parse this json response and create c# object
{"Response":"valid","Files":{"0":{"FileURL":"htp:\/\/somedomain.com\/1.exe","FileVersion":1},"1":{"FileURL":"htp:\/\/somedomain.com\/1.exe","FileVersion":2}}}
i have c# class
public class Files
{
public string fileURL;
public string fileVersion;
}
WebClient wc=new WebClient();
string code=wc.DownloadString("http://somedomain.com/GetLatestFiles.php");
List<Files> f=ParseJson(code);
how can i parse this json please help. I need to implement ParseJson which will return files list or can i deserialize this response to c# class?
Thankyou
Edit implemented some solution but its very slow?
public class LatestFile
{
public string fileURL;
public string fileVersion;
}
private List<LatestFile> ParseJson(string code)
{
List<LatestFile> files = new List<LatestFile>();
dynamic jObj = JsonConvert.DeserializeObject(code);
foreach (var child in jObj.Files.Children())
{
string index = child.Name;
string url = child.First.FileURL.Value;
string version = child.First.FileVersion.Value.ToString();
LatestFile f = new LatestFile();
f.fileURL = url;
f.fileVersion = version;
files.Add(f);
}
return files;
}
Based on #Brian Rogers answer below i am able to implement the generic solution working fast and efficiently.Thanks
https://dotnetfiddle.net/tC0Dws
Try defining your classes like this:
public class RootObject
{
public string Response { get; set; }
public Dictionary<string, LatestFile> Files { get; set; }
}
public class LatestFile
{
public string FileURL { get; set; }
public string FileVersion { get; set; }
}
And make your helper method like this:
private List<LatestFile> ParseJson(string json)
{
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
return obj.Files.Values.ToList();
}
Fiddle: https://dotnetfiddle.net/vpre5H
According to the JSON you provided you have three different objects there. First with Response and Files fields. Second - it looks like it's intended to be a collection but with current implementation it's an object - with fields 0 and 1. And third one with fields FileURL and FileVersion.
You can use DataContractJsonSerializer which is available starting from .Net 4.5. It's in System.Runtime.Serialization.Json namespace.
To parse your JSON you need following data structure:
[DataContract]
public class JsonResponse
{
[DataMember(Name = "Response")]
public string Response { get; set; }
[DataMember(Name = "Files")]
public Files Files { get; set; }
}
[DataContract]
public class Files
{
[DataMember(Name = "0")]
public MyFile Frst { get; set; }
[DataMember(Name = "1")]
public MyFile Scnd { get; set; }
}
[DataContract]
public class MyFile
{
[DataMember(Name = "FileURL")]
public string FileURL { get; set; }
[DataMember(Name = "FileVersion")]
public int FileVersion { get; set; }
}
To make testing easier I'm using your sample as a string but you can easily use URL or a Stream:
static string json = #"
{
""Response"":""valid"",
""Files"":
{
""0"":
{
""FileURL"":""htp:\/\/somedomain.com\/1.exe"",""FileVersion"":""1""
},
""1"":
{
""FileURL"":""htp:\/\/somedomain.com\/1.exe"",""FileVersion"":""2""
}
}
}";
static void Main(string[] args)
{
var serializer = new DataContractJsonSerializer(typeof(JsonResponse));
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(JsonResponse));
using (MemoryStream ms = new MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(json)))
{
JsonResponse response = (JsonResponse)js.ReadObject(ms);
}
}
And that's the result:
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 :-)