Json deserialize from wikipedia api with c# - c#

I have a wikipedia api with json format. Now I want to get the extract information from this api. I want to make it dynamic for any wikipedia api. [My wikipedia api][1]. I got following information from jsontoCsharp
namespace Json_deserialize
{
public class pageval
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public string extract { get; set; }
}
public class Query
{
public Dictionary<string, pageval> pages { get; set; }
}
public class Limits
{
public int extracts { get; set; }
}
public class RootObject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
public Limits limits { get; set; }
}
class Short_text
{
public static RichTextBox txt1 = new RichTextBox();
public static void shortText()
{
using (WebClient wc = new WebClient())
{
var client = new WebClient();
var response = client.DownloadString("https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exlimit=max&explaintext&exintro&titles=Neuschwanstein%20Castle&redirects="); ;
pageval m = JsonConvert.DeserializeObject<pageval>(response);
string result = m.extract;
txt1.Text = result;
}
}
}
}
I want to make such a coding which should be dynamic. That means the id 240912 should be varied in time. I tried a lot. but cannot get a satisfied result.

All JSON objects are essentially dictionaries. However, it usually makes sense to represent them as classes in C#, assuming the schema is constant. For cases where property names are not always the same, it's impossible to write a class to represent the object; so you much use dynamic or a dictionary
public class pageval
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public string extract { get; set; }
}
public class Query
{
public Dictionary<string, pageval> pages { get; set; }
}
public class Limits
{
public int extracts { get; set; }
}
public class RootObject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
public Limits limits { get; set; }
}
To get the extract:
var response = client.DownloadString("https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exlimit=max&explaintext&exintro&titles=Neuschwanstein%20Castle&redirects="); ;
var responseJson = JsonConvert.DeserializeObject<RootObject>(response);
var firstKey = responseJson.query.pages.First().Key;
var extract = responseJson.query.pages[firstKey].extract;

Related

Deserialize JSON USGS Earthquake Catalog API

I've recently completed the Treehouse online course "C# Streams and Data Processing" and one of the lessons in the course showed how to use Webclient to query an API and parse the data returned. The example shown used a Microsoft Bing API to retrieve data about soccer players, but I'm trying to create my own project using a different API, which is the USGS Earthquake Catalog. It shows data about recent earthquakes:
USGS Earthquake Catalog
I've got the Webclient working and am getting the return data. I've created a new class for the data and have pasted it as JSON, but I'm not sure why I can't access the properties in my code?
what I'd like to be able to do is run a loop to iterate through the data and show the magnitude, location and time.
namespace Earthquakes
{
class Program
{
static void Main(string[] args)
{
GetEarthquakes();
}
public static void GetEarthquakes()
{
var webClient = new WebClient();
byte[] earthquakeBytes = webClient.DownloadData("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2020-08-01&endtime=2020-08-02");
var serializer = new JsonSerializer();
using (var stream = new MemoryStream(earthquakeBytes))
using (var reader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(reader))
{
string jsonString = "";
var earthquake = JsonConvert.DeserializeObject<Earthquakes>(jsonString);
Console.WriteLine(earthquake.Metadata.title);
}
}
}
}
And the class:
namespace Earthquakes
{
public class Metadata
{
public long Generated { get; set; }
public string url { get; set; }
public string title { get; set; }
public int status { get; set; }
public string api { get; set; }
public int count { get; set; }
}
public class Properties
{
[JsonProperty("mag")]
public double Magnitude { get; set; }
[JsonProperty("place")]
public string Place { get; set; }
public object Time { get; set; }
public object Updated { get; set; }
public object Tz { get; set; }
public string Url { get; set; }
public string Detail { get; set; }
public int? Felt { get; set; }
public double? Cdi { get; set; }
public double? Mmi { get; set; }
public string Alert { get; set; }
public string Status { get; set; }
public int Tsunami { get; set; }
public int Sig { get; set; }
public string Net { get; set; }
public string Code { get; set; }
public string Ids { get; set; }
public string Sources { get; set; }
public string Types { get; set; }
public int? Nst { get; set; }
public double? Dmin { get; set; }
public double Rms { get; set; }
public double? Gap { get; set; }
public string MagType { get; set; }
public string Type { get; set; }
public string Title { get; set; }
}
public class Geometry
{
public string type { get; set; }
public List<double> coordinates { get; set; }
}
public class Feature
{
public string type { get; set; }
public Properties properties { get; set; }
public Geometry geometry { get; set; }
public string id { get; set; }
}
public class Earthquakes
{
public string Type { get; set; }
public Metadata Metadata { get; set; }
public List<Feature> Features { get; set; }
public List<double> Bbox { get; set; }
}
}
A few points:
It seems the main problem in your code is that you are completely ignoring the data you are downloading and instead you are deserializing an empty string. You can actually simplify your code quite a bit by using the DownloadString method instead of DownloadData. Then you can fetch the JSON and deserialize it in just a couple lines of code:
webClient.Encoding = Encoding.UTF8;
var json = webClient.DownloadString("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2020-08-01&endtime=2020-08-02");
var quakes = JsonConvert.DeserializeObject<Earthquakes>(json);
You don't actually need to include properties for everything in the JSON if you are only interested in a few things. If you only want magnitude, place and time, then your model classes could be as simple as this:
class Earthquakes
{
public List<Feature> Features { get; set; }
}
class Feature
{
public Properties Properties { get; set; }
}
class Properties
{
[JsonProperty("mag")]
public decimal Magnitude { get; set; }
public string Place { get; set; }
[JsonProperty("time")]
public long TimeMs { get; set; }
public DateTime Time => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(TimeMs);
}
Also notice that I have added a convenience method to convert the time value from the JSON into a readable date.
You have a namespace called Earthquakes and a class Earthquakes within it. While this is legal in C#, it makes the code harder to understand. I would recommend renaming one or the other so they are not the same. For example, you could rename the namespace EarthquakeDemo or rename the class EarthquakeInfo. Up to you of course. Also, I would recommend making the GetEarthquakes() method return the earthquakes it fetches instead of being a void method. Then you can separate the fetch logic from the display logic.
Here is a working demo with the above changes applied and display logic added: https://dotnetfiddle.net/uRg48y

How to get values from API?

I apologize for this post because it may seem banal to some people. But I would like to understand the operation of the GET API, unfortunately, somehow I have not found an accessible tutorial. As the best way to learn from examples, could anyone show me how to get the values from the name tag in the easiest way? can be up to textBox.
In xml:
https://bdl.stat.gov.pl/api/v1/subjects?lang=pl&format=xml
In json:
https://bdl.stat.gov.pl/api/v1/subjects?lang=pl&format=json
Code
public class Result
{
public string id { get; set; }
public string name { get; set; }
public bool hasVariables { get; set; }
public List<string> children { get; set; }
public string levels { get; set; }
}
private void button1_Click(object sender, EventArgs e)
{
using (WebClient wc = new WebClient())
{
wc.Encoding = System.Text.Encoding.UTF8;
var json = wc.DownloadString("https://bdl.stat.gov.pl/api/v1/subjects?lang=pl&format=json");
Result result = JsonConvert.DeserializeObject<Result>(json);
richTextBox1.Text = result.name;
}
}
Thank you in advance for your help.
You are missing various classes in order to get your JSON string Deserialized properly. Try like:
public class Results
{
public string id { get; set; }
public string name { get; set; }
public bool hasVariables { get; set; }
public List<string> children { get; set; }
public string levels { get; set; }
}
public class Links
{
public string first { get; set; }
public string self { get; set; }
public string next { get; set; }
public string last { get; set; }
}
public class JsonObject
{
public int totalRecords { get; set; }
public int page { get; set; }
public int pageSize { get; set; }
public Links links { get; set; }
public List<Results> results { get; set; }
}
And then use like:
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString("https://bdl.stat.gov.pl/api/v1/subjects?lang=pl&format=json");
JsonObject result = JsonConvert.DeserializeObject<JsonObject>(json);
foreach (var res in result.results)
{
MessageBox.Show(res.name);
}
}

Need assign List object parsed from JSON file to a object property

I trying to build Magic The Gathering card viewer and getting data from json. I have created json file, then copy all and paste special to my class to generate a model. In constructor using json parser I parsed object fine, but when I try to assign to that object property, so I can make method retrieve all cards. But when I trying to do that it says that I can't implicitly assign. I try to assign Cards = cardsCollection; that where it throws an error.
namespace MTGArena
{
public class Cards
{
public class Rootobject
{
static Rootobject()
{
using (StreamReader file = new StreamReader("cards.json"))
{
string json = file.ReadToEnd();
Rootobject cardsCollection = JsonConvert.DeserializeObject<Rootobject>(json);
Cards = cardsCollection;
}
}
public static List<Card> Cards { get; set; }
public static List<Card> GetCards()
{
return Cards;
}
}
}
public class Card
{
public string name { get; set; }
public string set { get; set; }
public Images images { get; set; }
public string type { get; set; }
public string[] cost { get; set; }
public int cmc { get; set; }
public string rarity { get; set; }
public string cid { get; set; }
public int?[] frame { get; set; }
public string artist { get; set; }
public string dfc { get; set; }
public bool collectible { get; set; }
public bool craftable { get; set; }
public int dfcId { get; set; }
public int rank { get; set; }
public string grpId { get; set; }
}
public class Images
{
public string small { get; set; }
public string normal { get; set; }
public string large { get; set; }
public string art_crop { get; set; }
}
}
Change the line:
Rootobject cardsCollection = JsonConvert.DeserializeObject<Rootobject>(json);
for:
var cardsCollection = JsonConvert.DeserializeObject<List<Card>>(json);
You need to use below syntax
IList<Card> cards = cardsCollection;
dont create empty Cards class. It has no use

Get all the titles after deserialiaztion json using C# and Json.net

I am using a wikipedia api which contains external links of all places from a wikipedia article. My wikipedia api call is:
https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=Berlin&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json
I make c# classes for json object using JsonToCsharp as follows:
public class Geosearch
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public double lat { get; set; }
public double lon { get; set; }
public double dist { get; set; }
public string primary { get; set; }
public string type { get; set; }
public string name { get; set; }
public object dim { get; set; }
public string country { get; set; }
public string region { get; set; }
}
public class Query
{
public List<Geosearch> geosearch { get; set; }
}
public class RootObject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
}
My deserialization code is as follows.With this code I got only one Title. But I want to get all the title from this api. I know I should make a foreach loop, but could not get logic how to implement it.
static void Main(string[] args)
{
WebClient client = new WebClient();
var GeoResponse = client.DownloadString("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=Berlin&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json");
RootObject json = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<RootObject>(GeoResponse);
var firstKey = json.query.geosearch.First().title;
Console.WriteLine(firstKey);
}
This works fine -
var o = new HttpClient();
var res = new StreamReader(o.GetStreamAsync("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=Berlin&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json").Result).ReadToEnd() ;
var obj = JsonConvert.DeserializeObject<RootObject>(res).query.geosearch.Select(a => a.title).ToList();
// count == 500
obj.Foreach(a => Console.WriteLine(a));
I just modified my code and It is working perfectly.
var response = client.GetAsync("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=Berlin&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json").Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
var obj = JsonConvert.DeserializeObject<RootObject>(responseString).query.geosearch.Select(a => a.title).ToList();
foreach (var item in obj)
{
Console.WriteLine(item);
}
}
}

What is the right C# structure to deserialize this json into?

I am getting json back from an http and I am trying to deserialized it into a C# object and it keeps coming back as null so my guess is that my data structure is off. Here is my code:
results = httpClient.GetStringAsync(url).Result;
var restResponse = new RestSharp.RestResponse();
restResponse.Content = results;
var deserializer = new JsonDeserializer();
var page = _deserializer.Deserialize<Tree>(restResponse);
Here is the Json:
{
"page":{
"results":[
{
"id":"144111690",
"type":"page",
"status":"current",
"title":"Title 1"
},
{
"id":"157540319",
"type":"page",
"status":"current",
"title":"Title 2"
},
{
"id":"144082624",
"type":"page",
"status":"current",
"title":"Title 3"
}
],
"start":0,
"limit":25,
"size":14
}
}
and Here are my C# objects:
public class Tree
{
public Results page { get; set; }
}
public class Results
{
public ResultDetails results { get; set; }
}
public class ResultDetails
{
public List<PageInfo> Pages { get; set; }
}
public class PageInfo
{
public long id { get; set; }
public string type { get; set; }
public string status { get; set; }
public string title { get; set; }
}
Can anyone advise on what is not "lining up" here?
Why don't you directly create class structure by using Visual studio ..that will give you class structure matching with your json.
you can check here how to generate : Visual Studio Generate Class From JSON or XML
Copy you json >> visual studio Edit menu > Paste Special >> Paste Json as class
This will work:
public class Tree
{
public Page page { get; set; }
}
public class Page
{
public List<Result> results { get; set; }
public int start { get; set; }
public int limit { get; set; }
public int size { get; set; }
}
public class Result
{
public string id { get; set; }
public string type { get; set; }
public string status { get; set; }
public string title { get; set; }
}
results is an array in JSON, but you defined it as an object (ResultDetails)
This might do the trick for you
public class Rootobject
{
[JsonProperty("page")]
public Page page { get; set; }
}
public class Page
{
[JsonProperty("results")]
public Result[] results { get; set; }
[JsonProperty("start")]
public int start { get; set; }
[JsonProperty("limit")]
public int limit { get; set; }
[JsonProperty("size")]
public int size { get; set; }
}
public class Result
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("type")]
public string type { get; set; }
[JsonProperty("status")]
public string status { get; set; }
[JsonProperty("title")]
public string title { get; set; }
}
And the implementation should be
results = httpClient.GetStringAsync(url).Result;
var restResponse = new RestSharp.RestResponse();
restResponse.Content = results;
var deserializer = new JsonDeserializer();
var page = _deserializer.Deserialize<Rootobject>(restResponse);

Categories

Resources