How to get title of landmark place from Wikipedia by API? - c#

For my code I am using the Wikipedia API which provides links to all places that are linked with the Wikipedia article of that city. But with my code there are some extra unnecessary links. I want to only return links where the type is "landmark".
My Wikipedia API 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
Sample JSON data from the Wikipedia API:
"query": {
"geosearch": [
{
"pageid": 5858187,
"ns": 0,
"title": "Stuttgart Hauptbahnhof",
"lat": 48.783888888889,
"lon": 9.1816666666667,
"dist": 136.8,
"primary": "",
"type": "railwaystation",
"name": "",
"dim": 1000,
"country": "DE",
"region": "BW"
},
{
"pageid": 6102287,
"ns": 0,
"title": "Staatstheater Stuttgart",
"lat": 48.780277777778,
"lon": 9.185,
"dist": 361,
"primary": "",
"type": "landmark",
"name": "",
"dim": "900",
"country": "DE",
"region": "BW"
},
{
"pageid": 35806545,
"ns": 0,
"title": "Versatel building",
"lat": 48.78409,
"lon": 9.17799,
"dist": 400.4,
"primary": "",
"type": null,
"name": "",
"dim": 1000,
"country": null,
"region": null
},
{
"pageid": 3230957,
"ns": 0,
"title": "Neue Staatsgalerie",
"lat": 48.780277777778,
"lon": 9.1869444444444,
"dist": 430.6,
"primary": "",
"type": "landmark",
"name": "",
"dim": 1000,
"country": "DE",
"region": "BW"
},
....
]
}
My code to get the Title from this API.
using (var client = new HttpClient())
{
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);
}
}
}
Here is the current output:
How can I get the title from the results where the type is "landmark"?

If you use JSON format, try this:
var obj = JsonConvert.DeserializeObject<RootObject>(responseString).query.geosearch
.Where(a => a.type == "landmark").Select(a => a.title).ToList();
Also you can get all titles without to use Json.NET. This is how I do it with XML format:
using (var webResponse = (HttpWebResponse)WebRequest.Create("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=Berlin&gslimit=500&gsprop=type&format=xml").GetResponse())
{
using (var reader = new StreamReader(webResponse.GetResponseStream()))
{
var response = XElement.Parse(reader.ReadToEnd());
var obj = response.Descendants("gs")
.Where(a => a.Attribute("type") != null && a.Attribute("type").Value == "landmark")
.Select(a => a.Attribute("title").Value).ToList();
}
}

I don't know C# :-)
But try something like this:
var geosearch = JsonConvert.DeserializeObject<RootObject>(responseString).query.geosearch;
var landmarks = geosearch.Where(type => type == "landmark");

Related

Columns not returning correctly when using WIQL Queries from ADO

I am trying to get all Epics from ADO using the below code
string PAT = "sdsd";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", PAT))));
string query = "SELECT [System.Id], [System.WorkItemType], [System.Title], [System.State], [System.AreaPath], [System.IterationPath], [System.TeamProject], [System.WorkItemType] FROM workitems WHERE System.WorkItemType='Epic' ORDER BY [System.ChangedDate] DESC ";
var q = JsonConvert.SerializeObject(new WiqlQuery() { query = query });
using (HttpResponseMessage response =client.PostAsync("https://dev.azure.com/{Org}/_apis/wit/wiql?api-version=6.0",new StringContent(q,Encoding.UTF8,"application/json")).GetAwaiter().GetResult())
{
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
string k = "";
}
}
Code executes without any trouble. But if I run the above query in ADO query editor, its returning all the columns in the Select statement.
But when I run the same in Code, I am not all getting any of those columns. Instead I am getting below JSON
{
"queryType": "flat",
"queryResultType": "workItem",
"asOf": "2021-07-02T08:30:15.84Z",
"columns": [
{
"referenceName": "System.Id",
"name": "ID",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.Id"
},
{
"referenceName": "System.WorkItemType",
"name": "Work Item Type",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.WorkItemType"
},
{
"referenceName": "System.Title",
"name": "Title",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.Title"
},
{
"referenceName": "System.State",
"name": "State",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.State"
},
{
"referenceName": "System.AreaPath",
"name": "Area Path",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.AreaPath"
},
{
"referenceName": "System.IterationPath",
"name": "Iteration Path",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.IterationPath"
},
{
"referenceName": "System.TeamProject",
"name": "Team Project",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.TeamProject"
},
{
"referenceName": "System.WorkItemType",
"name": "Work Item Type",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.WorkItemType"
}
],
"sortColumns": [
{
"field": {
"referenceName": "System.ChangedDate",
"name": "Changed Date",
"url": "https://dev.azure.com/{organization}/_apis/wit/fields/System.ChangedDate"
},
"descending": true
}
],
"workItems": [
{
"id": 61380,
"url": "https://dev.azure.com/{organization}/_apis/wit/workItems/613810"
},
{
"id": 61834
}
]
}
What could be the reason or how to get all the columns of data we have specified in Select statement
Yes, RUN WIQL returns only the list of ids. Then you can use Get Work Items Batch to get only needed fields:
POST https://dev.azure.com/fabrikam/_apis/wit/workitemsbatch?api-version=6.1-preview.1
BODY:
{
"ids": [
297,
299,
300
],
"fields": [
"System.Id",
"System.Title",
"System.WorkItemType",
"Microsoft.VSTS.Scheduling.RemainingWork"
]
}

Odata2 Filtering parent or children of different types

I am trying to filter nested data but the catch is, the children I am also trying to filter are of a different type.
I have data that looks like this:
{
"value": [
{
"UserName": "scottketchum",
"FirstName": "Scott",
"LastName": "Ketchum",
"MiddleName": null,
"Gender": "Male",
"Age": null,
"Emails": [
"Scott#example.com"
],
"FavoriteFeature": "Feature1",
"Features": [],
"AddressInfo": [
{
"Address": "2817 Milton Dr.",
"City": {
"Name": "Albuquerque",
"CountryRegion": "United States",
"Region": "NM"
}
}
],
"HomeAddress": null
},
{
"UserName": "harryingram",
"FirstName": "Harry",
"LastName": "Ingram",
"MiddleName": null,
"Gender": "Male",
"Age": null,
"Emails": [
"Harry#example.com"
],
"FavoriteFeature": "Feature2",
"Features": [],
"AddressInfo": [
{
"Address": "123 Scott Ln.",
"City": {
"Name": "Nashville",
"CountryRegion": "United States",
"Region": "TN"
}
}
],
"HomeAddress": null
}
]
}
I need to be able to type the word "Scott" in my search field and return any person that has the name "Scott" or has an Address with the word "Scott" in it. So, ideally, the search would return both people.
void searchitemfromjson(string s)
{
var text = File.ReadAllText("D://jsontest.txt");
var jObject1 = JObject.Parse(text)["value"];
var searchs = new List<string>();
foreach (var item in jObject1)
{
var jObjitem = JObject.Parse(item.ToString());
IList<string> keys = jObjitem.Properties().Select(p => p.Name).ToList();
foreach (var k in keys)
{
if (k == "UserName")
{
if (jObjitem[k].ToString().Contains(s)) searchs.Add(jObjitem[k].ToString());
}
else if(k == "AddressInfo")
{
if(jObjitem["AddressInfo"][0]["Address"].ToString().Contains(s)) searchs.Add(jObjitem[k].ToString()); ;
}
}
}
}

Nested JSON data to datatable dynamically C#

{
"STATUS": "OK",
"projects": [
{
"startDate": "",
"last-changed-on": "2019-01-03T11:46:14Z",
"logo": "",
"created-on": "2018-12-12T10:04:47Z",
"privacyEnabled": false,
"status": "active",
"boardData": {},
"replyByEmailEnabled": true,
"harvest-timers-enabled": false,
"description": "",
"category": {
"color": "",
"id": "",
"name": ""
},
"id": "322852",
"overview-start-page": "default",
"start-page": "projectoverview",
"integrations": {
"xero": {
"basecurrency": "",
"countrycode": "",
"enabled": false,
"connected": "NO",
"organisation": ""
},
"sharepoint": {
"account": "",
"foldername": "root",
"enabled": false,
"folder": "root"
},
"microsoftConnectors": {
"enabled": false
},
"onedrivebusiness": {
"account": "",
"foldername": "root",
"enabled": false,
"folder": "root"
}
},
"defaults": {
"privacy": ""
},
"notifyeveryone": false,
"filesAutoNewVersion": false,
"defaultPrivacy": "open",
"tasks-start-page": "default",
"starred": false,
"announcementHTML": "",
"isProjectAdmin": true,
"name": "Project 2",
"company": {
"is-owner": "1",
"id": "78494",
"name": "MCG Company"
},
"endDate": "",
"announcement": "",
"show-announcement": false,
"subStatus": "current",
"tags": []
},
{
"startDate": "",
"last-changed-on": "2018-12-11T17:52:57Z",
"logo": "",
"created-on": "2018-11-26T11:11:00Z",
"privacyEnabled": false,
"status": "active",
"boardData": {},
"replyByEmailEnabled": true,
"harvest-timers-enabled": false,
"description": "",
"category": {
"color": "",
"id": "",
"name": ""
},
"id": "321041",
"overview-start-page": "default",
"portfolioBoards": [
{
"card": {
"id": "4771"
},
"board": {
"id": "544",
"name": "Project Implementations",
"color": "#F39C12"
},
"column": {
"id": "1573",
"name": "Go Live",
"color": "#F1C40F"
}
}
],
"start-page": "projectoverview",
"integrations": {
"xero": {
"basecurrency": "",
"countrycode": "",
"enabled": false,
"connected": "NO",
"organisation": ""
},
"sharepoint": {
"account": "",
"foldername": "root",
"enabled": false,
"folder": "root"
},
"microsoftConnectors": {
"enabled": false
},
"onedrivebusiness": {
"account": "",
"foldername": "root",
"enabled": false,
"folder": "root"
}
},
"defaults": {
"privacy": ""
},
"notifyeveryone": false,
"filesAutoNewVersion": false,
"defaultPrivacy": "open",
"tasks-start-page": "default",
"starred": false,
"announcementHTML": "",
"isProjectAdmin": true,
"name": "Project One",
"company": {
"is-owner": "1",
"id": "78494",
"name": "MCG Company"
},
"endDate": "",
"announcement": "",
"show-announcement": false,
"subStatus": "current",
"tags": []
}
]
}
This is the JSON response that I'm getting from an app, and there are a lot of other API gets that are returning the same kind of response (nested), so this has to be done dynamically as the user is adding API calls from a config file, so I cannot make pre-made classes with gets and sets.
My goal is to transform this data into a datatable to be inserted into a database
When I see a nested column, my goal is to have the parent column name attached to it with an "_" ex: category_id = ""
or integrations_xero_basecurrency = "", etc..
This is the code that I used to tabulate the data, but in the code it's only taking the column if it's a JValue (key and value), and I'm not able for the life of me to create a proper loop that will do the trick.
public DataTable Tabulate(string jsonContent)
{
var jsonLinq = JObject.Parse(jsonContent);
// Find the first array using Linq
var srcArray = jsonLinq.Descendants().Where(d => d is JArray).First();
//Console.WriteLine("extarcted data:" + srcArray);
var trgArray = new JArray();
foreach (JObject row in srcArray.Children<JObject>())
{
var cleanRow = new JObject();
foreach (JProperty column in row.Properties())
{
// Only include JValue types
if (column.Value is JValue)
{
cleanRow.Add(column.Name, column.Value);
}
}
trgArray.Add(cleanRow);
}
DataTable dt = JsonConvert.DeserializeObject<DataTable>(trgArray.ToString());
return dt;
}
How about something like this:
public DataTable Tabulate(string jsonContent)
{
var jsonLinq = JObject.Parse(jsonContent);
// Find the first array using Linq
var arrayProp = jsonLinq.Properties().First(p => p.Value is JArray);
var srcArray = (JArray)arrayProp.Value;
// Set up a regex consisting of the array property name and subscript
// (e.g. "projects[0]."), which we will strip off
var regex = new Regex($#"^{arrayProp.Name}\[\d+\]\.");
// Flatten each object of the original array
// into new objects and put them in a new array
var trgArray = new JArray(
srcArray.Children<JObject>()
.Select(row => new JObject(
row.Descendants()
.OfType<JProperty>()
.Where(p => p.Value is JValue)
.Select(p => new JProperty(
regex.Replace(p.Value.Path, "").Replace(".", "_"),
p.Value
))
))
);
// Convert the new array to a DataTable
DataTable dt = trgArray.ToObject<DataTable>();
return dt;
}
Working demo: https://dotnetfiddle.net/yrmcSQ

Unity Facebook SDK, retrieve data from 'apprequests' from API

I am fetching /me/apprequests from Facebook API. It works and I get the data in JSON format.
Thing is that everything is nested, like a dictionary inside a dictionary.
What i tried:
Dictionary<string, object> dict = Facebook.MiniJSON.Json.Deserialize(result.RawResult) as Dictionary<string, object>;
object data;
string request_code = "";
if (dict.TryGetValue("data", out data))
{
var rc = (((Dictionary<string, object>)data)["id"]);
request_code = (string)rc;
}
Debug.Log("request_code=" + request_code);
I think I need to loop the dictionary to get all id's.
I can confirm that if (dict.TryGetValue("data", out data)) does work correctly and get the dictionary of data arrays, but fails here (((Dictionary<string, object>)data)["id"]); with casting error.
Json looks like:
{
"data": [{
"application": {
"category": "Games",
"link": "https:\/\/www.facebook.com\/games\/?app_id=2523532533",
"name": "game name",
"id": "23432423423"
},
"created_time": "2019-02-27T16:01:15+0000",
"from": {
"name": "David boom",
"id": "387923432423089962"
},
"message": "You are invited",
"to": {
"name": "Dusty Spice",
"id": "10234324421033685"
},
"id": "413880842521239_10156578101000000"
},
{
"application": {
"category": "Games",
"link": "https:\/\/www.facebook.com\/games\/?app_id=2523532533",
"name": "game name",
"id": "23432423423"
},
"created_time": "2019-02-27T14:12:41+0000",
"from": {
"name": "David boom2",
"id": "387923432423089962"
},
"message": "You are invited",
"to": {
"name": "Dusty Spice",
"id": "10234324421033685"
},
"id": "316676422209302_10156578101000000"
}],
"paging": {
"cursors": {
"before": "NDEzODgwODQyNTIxMjM5Ojc1OTQzODY4NAZDZD",
"after": "MzE2Njc2NDIyMjA5MzAyOjc1OTQzODY4NAZDZD"
}
}
}
Managed to make it work if it will help someone:
string request_code = "";
if (dict.TryGetValue("data", out data))
{
int dataLength = ((List<object>)data).Count;
for (int i = 0; i < dataLength; i++)
{
var rc = ((List<object>)data)[i];
var rc2 = (((Dictionary<string, object>)rc)["id"]);
request_code = (string)rc2;
Debug.Log("request_code=" + request_code);
}
}

How to parse Twitter Trends Json response

I am trying to parse the following JSon to access the name property. But I am having some difficulty.
{[
{
"trends": [
{
"name": "#penaltypointsforpricks",
"url": "http://twitter.com/search?q=%23penaltypointsforpricks",
"promoted_content": null,
"query": "%23penaltypointsforpricks",
"events": null
},
{
"name": "#sometimesiwishthat",
"url": "http://twitter.com/search?q=%23sometimesiwishthat",
"promoted_content": null,
"query": "%23sometimesiwishthat",
"events": null
},
{
"name": "#1000daysof1d",
"url": "http://twitter.com/search?q=%231000daysof1d",
"promoted_content": null,
"query": "%231000daysof1d",
"events": null
},
{
"name": "#ireland",
"url": "http://twitter.com/search?q=%23ireland",
"promoted_content": null,
"query": "%23ireland",
"events": null
},
{
"name": "#savita",
"url": "http://twitter.com/search?q=%23savita",
"promoted_content": null,
"query": "%23savita",
"events": null
},
{
"name": "Twitter",
"url": "http://twitter.com/search?q=Twitter",
"promoted_content": null,
"query": "Twitter",
"events": null
},
{
"name": "Cork",
"url": "http://twitter.com/search?q=Cork",
"promoted_content": null,
"query": "Cork",
"events": null
},
{
"name": "Facebook",
"url": "http://twitter.com/search?q=Facebook",
"promoted_content": null,
"query": "Facebook",
"events": null
},
{
"name": "Boston",
"url": "http://twitter.com/search?q=Boston",
"promoted_content": null,
"query": "Boston",
"events": null
},
{
"name": "Will",
"url": "http://twitter.com/search?q=Will",
"promoted_content": null,
"query": "Will",
"events": null
}
],
"as_of": "2013-04-18T18:34:45Z",
"created_at": "2013-04-18T18:29:40Z",
"locations": [
{
"name": "Dublin",
"woeid": 560743
}
]
}
]}
I had the following suggestion but it returns a null reference exception during run time.
var twitterObject = JToken.Parse(jsonString);
var trendsArray = twitterObject.Children<JProperty>().FirstOrDefault(x => x.Name == "trends").Value;
foreach (var item in trendsArray.Children())
{
var itemProperties = item.Children<JProperty>();
//you could do a foreach or a linq here depending on what you need to do exactly with the value
var myElement = itemProperties.FirstOrDefault(x => x.Name == "url");
var myElementValue = myElement.Value; ////This is a JValue type
}
Anyone have any suggestions how to parse this json response to get each individual "name"
I was able to get the names using this.
dynamic dynObj = JsonConvert.DeserializeObject(jsonString);
foreach (var trend in dynObj[0].trends)
{
Console.WriteLine(trend.name);
}
It'd probably be better to write classes for the JSON objects if you plan to grab anything more than the name, but I hope this helps.

Categories

Resources