Json child access yahoo weather json in C# - c#

So I'm trying to get the weather from the Yahoo's weather Json, but the thing is I keep getting this error
{"Cannot access child value on Newtonsoft.Json.Linq.JValue."}
Right now I have no idea why is this happening. I checked the parenting a few times already, the spelling and all that.
public String GetWeather() {
StringBuilder theWebAddress = new StringBuilder();
theWebAddress.Append("https://query.yahooapis.com/v1/public/yql?");
theWebAddress.Append("q=" + System.Web.HttpUtility.UrlEncode("select * from weather.forecast where woeid in (select woeid from geo.places(1) where text='"+ city + ", "+ state + "') and u='" + units +"'"));
theWebAddress.Append("&format=json");
theWebAddress.Append("&diagnostics=false");
string results = "";
using (WebClient wClient = new WebClient())
{
results = wClient.DownloadString(theWebAddress.ToString());
}
JObject dataObject = JObject.Parse(results);
JArray jsonArray = (JArray)dataObject["query"]["results"]["channel"]; //This is the line that is generating the error.
foreach (var woeid in jsonArray)
{
//stocheaza informatiile in variabile
condition = woeid["item"]["condition"]["text"].ToString();
//System.Diagnostics.Debug.WriteLine(condition);
return condition;
}
return null;
}
The link to the API is here. So as far as I see, there is problem with getting the child of query or results. Any ideas? Thanks in advance.

I solved it by changing the code. Instead of using that code, I changed it with this
public string GetWeather(string info)
{
string results = "";
using (WebClient wc = new WebClient())
{
results = wc.DownloadString("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%27galati%2C%20ro%27)%20and%20u%3D%22c%22&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
}
dynamic jo = JObject.Parse(results);
if (info == "cond")
{
var items = jo.query.results.channel.item.condition;
condition = items.text;
return condition;
}
}
Now it works as intended.

Related

Call to Gmail API Update method is not generating an result or an error

So, i'm calling the method to update the primary "sendAs" object of a google account, without results. The documentation from google at users.settings.sendAs/update indicates all i need and did:
i've set the domain wide account and scopes
i'm generating a token and accessing it no problem
i'm calling the "list" method first (with that token) as shown in users.settings.sendAs/list documentation, and finding the one that is the primary (the "isPrimary" attribute is true)
After that, changing the "signature" value to "Its a Test Signature", and sending the PUT request with it doesn't do anything.
The JSON sent to the update API (via PUT method) is the exact one i collected from the list (the primary one), but with the signature changed.
There is no error at all, and i receive an "sendAs" object back as a response (as the documentation says i should in case of sucess), but the signature is unchanged.
What can i be?
EDIT (adding the code section for the call, again - no errors)
public bool Update()
{
string json = null;
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/json";
wc.Headers["Authorization"] = "Bearer " + GenerateServerToServerToken(this.OwnerMail, this.scope);
json = wc.DownloadString("https://gmail.googleapis.com/gmail/v1/users/" + this.OwnerMail + "/settings/sendAs");
JSon.Query response = JSon.Parse(ref json);
json = null;
response = response["sendAs"];
List<JSon.Query> mailAs = null;
if (response.TryParseList(out mailAs))
{
JSon.Query main = null;
bool prim = false;
foreach (JSon.Query q in mailAs)
{
if (q["isPrimary"].TryParseBoolean(out prim) && prim)
{
if (q["sendAsEmail"].TryParseString(out json)) { main = q; }
break;
} else { json = null; }
}
if (main != null)
{
JSon.ObjectValue mainO = (JSon.ObjectValue)main.Value;
if (mainO.ContainsKey("signature"))
{
((JSon.StringValue)mainO["signature"]).Data = this.HtmlSignature.Replace("<", ("\\" + "u003c")).Replace(">", ("\\" + "u003e"));
mainO["verificationStatus"] = new MdIO.JSon.StringValue("accepted");
json = wc.UploadString("https://gmail.googleapis.com/gmail/v1/users/" + this.OwnerMail + "/settings/sendAs/" + json, "PUT", main.Value.ToJSON());
response = JSon.Parse(ref json);
if (response["sendAsEmail"].TryParseString(out json) && !string.IsNullOrEmpty(json)) { return true; }
}
}
}
}
return false;
}

C# Count if Field Exists

Below is a script making an API call which retrieves some ReportIDs (from a database table), passes them through a method which will run them individually, and finally see if each contains the field, Name_First.
What I need help with is creating a count that will tell me how many reports contain the field Name_First, how many don't, and what's the percentage out of all reports having the field, Name_First.
Currently, the script queries two ReportIDs (12300,12301) for testing. One report has the field Name_First in it and the other one doesn't. From the foreach loop I've written, I'm aiming to count every time there is a null and every time there isn't, get a total, and just divide the not null count by the sum of both. However, when I run this script, the console at
Console.WriteLine(total);
Console.WriteLine(total_noFirstName);
Console.WriteLine(total_FirstName);
returns values of 0, 0, and 0. I think I'm having a scope issue here, but I'm not really sure. If I could receive some help solving this, I'd very much appreciate it.
Thank you!
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
namespace NameFirstSearch
{
class Program
{
static void Main(string[] args)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
const string username = "Username";
const string password = "Password";
const string baseUrl = "https://test.com/rest/services/";
const string queryString = "query?q=Select * From Report Where ReportID in (12300,12301)";
const string queryNameFirst = "getreport/";
var client = new HttpClient();
client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var auth = Convert.ToBase64String(Encoding.Default.GetBytes(username + ":" + password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth);
//GetReports(client, queryString).Wait();
var reportsList = GetReports(client, queryString).Result;
GetNameFirst(client, queryNameFirst, reportsList).Wait();
Console.ReadLine();
}
static async Task<List<Properties>> GetReports(HttpClient client, string queryString)
{
List<Properties> result = new List<Properties>();
var response = await client.GetAsync(queryString);
// Check for a successfull result
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<List<Properties>>(json);
}
else
{
// Error code returned
Console.WriteLine("No records found on first method.");
}
return result;
}
static async Task GetNameFirst(HttpClient client, string queryNameFirst, List<Properties> results)
{
string reportType = ".json";
foreach (var item in results)
{
var output = await client.GetAsync(queryNameFirst + item.ReportID + reportType);
if (output.IsSuccessStatusCode)
{
var allText = await output.Content.ReadAsStringAsync();
var fields = JsonConvert.DeserializeObject<List<FirstName>>(allText);
var test = JsonConvert.SerializeObject(fields);
Console.WriteLine(test);
int total_FirstName = 0;
int total_noFirstName = 0;
int total = total_FirstName + total_noFirstName;
foreach (var split in fields)
{
if (split.Name_First != null)
{
total_FirstName++;
}
else if (split.Name_First == null)
{
total_noFirstName++;
}
}
Console.WriteLine(total);
Console.WriteLine(total_noFirstName);
Console.WriteLine(total_FirstName);
}
else
{
// Error code returned
Console.WriteLine("No records found on second method.");
}
}
}
}
}
Class Properties
int ReportID {get; set;}
Class FirstName
string Name_First {get; set;}
Results at Console.WriteLine(test);
[{"Name_First":"Mario"}]
[{"Name_First":null}]
Results for Console.WriteLine(allText);
[{"Name_First":"Mario","Entry_ID":"72313"}]
[{"Name_Last":"Rincon Recio","Entry_ID":"72313"}]
If you want to keep a count of things in a loop, you need to declare the counter variables outside of the loop, otherwise they get reinitialised. Using your data from the question, the relevant loop should look like this:
List<string> allTexts = new List<string>
{ #"[{""Name_First"":""Mario"",""Entry_ID"":""72313""}]",
#"[{""Name_Last"":""Rincon Recio"",""Entry_ID"":""72313""}]" };
int total_FirstName = 0;
int total_noFirstName = 0;
foreach(var allText in allTexts)
{
var fields = JsonConvert.DeserializeObject<List<FirstName>>(allText);
var test = JsonConvert.SerializeObject(fields);
Console.WriteLine(test);
foreach (var split in fields)
{
if (split.Name_First != null)
{
total_FirstName++;
}
else
{
total_noFirstName++;
}
}
}
int total = total_FirstName + total_noFirstName;
Console.WriteLine(total);
Console.WriteLine(total_noFirstName);
Console.WriteLine(total_FirstName);
Output:
[{"Name_First":"Mario"}]
[{"Name_First":null}]
2
1
1

I used SvcUtil to create classes from WSDL. What do I deserialize into?

I used svcUtil.exe to create classes from https://gw.sam.gov/SAMWS/1.0/Entity?wsdl
but I cannot for the life of me find what to deserialize the result into? When I created my own classes the root is envelope but it isn't even in the new classes.
I can paste the classes but it is really long? Is there a general answer to this?
I will paste the classes upon request.
Thanks in advance...
The classes are over 10x too long to post.
Adding code for the pull:
static void Main(string[] args)
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var _url = "https://gw.sam.gov/SAMWS/1.0/Entity";
//Run date is a specific date if provided otherwise use yesterday
DateTime startDateTime = DateTime.Now.AddDays(-1).Date;
for (int hr = 0; hr < 24; hr++)
{
XMLclassRequest xmlSoap = new XMLclassRequest();
string soap = xmlSoap.BuildSOAPrequest(startDateTime.AddHours(hr));
//string soap2 = xmlSoap.BuildSOAPrequest2(startDateTime.AddHours(hr));
string response = null; //This is the original pull with FAR and DFAR Responses
//string response2 = null; //This is FAR and DFAR
using (MyWebClient client = new MyWebClient())
{
client.Headers.Add("Content-Type", "text/xml;charset=utf-8");
client.Headers.Add("SOAPAction", "\"http://tempuri.org/IMyService/MyOperation\"");
try
{
response = client.UploadString(_url, soap);
//response2 = client.UploadString(_url, soap2);
}
catch
{ } //This will skip the hour attempted and move to next. The error I have been receiving is no data which is differently formatted XML that causes the error
}
//File.WriteAllText(#"D:\temp\bigpull.xml", response);
MemoryStream stream = null;
if (response != null)
{
byte[] byteArray = Encoding.Unicode.GetBytes(response);
stream = new MemoryStream(byteArray);
}
getEntities results;
XmlSerializer serializer = new XmlSerializer(typeof(getEntities));
try
{ results = (getEntities)serializer.Deserialize(stream); }
catch
{ } //This will skip the hour attempted and move to next. The error I have been receiving is no data which is differently formatted XML that causes the error
stream.Close();
string str;
}
The response is coming back. I just can't get it into an object to use.
I couldn't get this loaded into an object but ended up loading it to an XDocument and parsed that:
var _url = "https://gw.sam.gov/SAMWS/1.0/Entity";
//Run date is a specific date if provided otherwise use yesterday
DateTime startDateTime = DateTime.Now.AddDays(-1).Date;
for (int hr = 0; hr < 24; hr++)
{
XMLclassRequest xmlSoap = new XMLclassRequest();
string soap = xmlSoap.BuildSOAPrequest(startDateTime.AddHours(hr));
//string soap2 = xmlSoap.BuildSOAPrequest2(startDateTime.AddHours(hr));
string response = null; //This is the original pull with FAR and DFAR Responses
//string response2 = null; //This is FAR and DFAR
using (MyWebClient client = new MyWebClient())
{
client.Headers.Add("Content-Type", "text/xml;charset=utf-8");
client.Headers.Add("SOAPAction", "\"http://tempuri.org/IMyService/MyOperation\"");
try
{
response = client.UploadString(_url, soap);
//response2 = client.UploadString(_url, soap2);
}
catch
{ } //This will skip the hour attempted and move to next. The error I have been receiving is no data which is differently formatted XML that causes the error
}
//File.WriteAllText(#"D:\temp\far20190604.xml", response);
XDocument xdoc = XDocument.Parse(response);
var entities = from e in xdoc.Descendants("entity") select e;
foreach (var e in entities)
{
string DUNS = e.Descendants("DUNS").FirstOrDefault().Value;
var provisions = from p in e.Descendants("provision") select p;
foreach (var p in provisions)
{
string ParentID = p.Descendants("id").FirstOrDefault().Value;
var answers = from a in p.Descendants("answer") select a;
foreach (var a in answers)
{
var section = a.Descendants("section").Count()>0? a.Descendants("section").FirstOrDefault().Value : "";
var answerText = a.Descendants("answerText").Count() > 0 ? a.Descendants("answerText").FirstOrDefault().Value : "";
Console.WriteLine(DUNS + " " + ParentID + " " + section + " " + answerText);
}
}
}

Convert JSON Source to c# ASP .NET Output

I'm trying to load data from https://www.quandl.com/api/v3/datatables/WIKI.
Comes out in a form like below
{"datatable":{"data":[["A","2017-11-14",66.98,67.8,66.89,67.46,1682158.0,0.0,1.0,66.98,67.8,66.89,67.46,1682158.0]],"columns":[{"name":"ticker","type":"String"},{"name":"date","type":"Date"},{"name":"open","type":"BigDecimal(34,12)"},{"name":"high","type":"BigDecimal(34,12)"},{"name":"low","type":"BigDecimal(34,12)"},{"name":"close","type":"BigDecimal(34,12)"},{"name":"volume","type":"BigDecimal(37,15)"},{"name":"ex-dividend","type":"BigDecimal(42,20)"},{"name":"split_ratio","type":"double"},{"name":"adj_open","type":"BigDecimal(50,28)"},{"name":"adj_high","type":"BigDecimal(50,28)"},{"name":"adj_low","type":"BigDecimal(50,28)"},{"name":"adj_close","type":"BigDecimal(50,28)"},{"name":"adj_volume","type":"double"}]},"meta":{"next_cursor_id":null}}.
However I try to load in asp .net like below but get an error saying it can't find data.
public partial class _Default : System.Web.UI.Page
{
protected string url = "https://www.quandl.com/api/v3/datatables/WIKI/PRICES?date=2017-11-14&ticker=A&api_key=<YOURAPIKEY>";
protected void Page_Load(object sender, EventArgs e)
{
//create an instance of HttpClient
HttpClient client = new HttpClient();
//DefaultRequestHeader to Json
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Create an instance of HttpResponse & invoke the service asynchronously
HttpResponseMessage response = client.GetAsync(url).Result;
//Http Status code 200
if (response.IsSuccessStatusCode)
{
//Read response content result into string variable
string JSON = response.Content.ReadAsStringAsync().Result;
//Deserialize the string(JSON) object
var jObj = (JObject)JsonConvert.DeserializeObject(JSON);
//access items from anonymous (Json object) type and add to the list
var result = jObj["datatable"].Select(item => new
{
key = item["data"][0],
code = item["data"][1],
description = item["data"][2],
buy = item["data"][3],
sell = item["data"][4],
}).ToList();
//output the data || NOTE: **NSERT into database table**
foreach (var item in result)
{
lblOutput.Text = item.key + "--" + item.code + "--" + item.description + item.buy + item.sell + "<br/>";
}
}
}
}
I can't seem to figure out how to load the data in the beginning bit of the json file
{"datatable":{"data":[["A","2017-11-14",66.98,67.8,66.89,67.46,1682158.0,0.0,1.0,66.98,67.8,66.89,67.46,1682158.0]],
You need to go over the data items not datatable items
var result = jObj["datatable"]["data"].Select(item => new
{
key = item[0],
code = item[1],
description = item[2],
buy = item[3],
sell = item[4],
}).ToList();

How to access a key named with asterisk?

There is a method in Wikimedia API that gives a localized title.
Examples:
Cloud:
http://en.wikipedia.org/w/api.php?format=json&action=query&titles=Cloud&prop=langlinks&lllimit=500&lllang=ru&continue=
Rain: http://en.wikipedia.org/w/api.php?format=json&action=query&titles=Rain&prop=langlinks&lllimit=500&lllang=ru&continue=
Cloud response:
{
"batchcomplete":"",
"query":{
"pages":{
"47515":{
"pageid":47515,
"ns":0,
"title":"Cloud",
"langlinks":[
{
"lang":"ru",
"*":"\u041e\u0431\u043b\u0430\u043a\u0430"
}
]
}
}
}
}
Rain response:
{
"batchcomplete":"",
"query":{
"pages":{
"19009110":{
"pageid":19009110,
"ns":0,
"title":"Rain",
"langlinks":[
{
"lang":"ru",
"*":"Дождь"
}
]
}
}
}
}
Important note: integer container under pages (e.g. 19009110) is always different, because it equals page id.
C# code:
dynamic datacontainer_RUname2 = JObject.Parse(cleanJson_string_RUname);
String localizedName = datacontainer_RUname.[HERE SHOULD BE *];
How can I access a key named with asterisk '*'?
string content;
using (var webClient = new WebClient())
{
const string url = "http://en.wikipedia.org/w/api.php?format=json&action=query&titles=Cloud&prop=langlinks&lllimit=500&lllang=ru&continue=";
content = webClient.DownloadString(url);
}
var obj = JObject.Parse(content);
var query = obj["query"];
var pages = query["pages"].Value<JObject>();
var page = pages.PropertyValues().First();
var langLinks = page["langlinks"].Values<JObject>();
var firstLangLink = langLinks.First();
var localizedName = firstLangLink["*"];
See a working demo with live data.
Just use the normal indexing on the object.
string localizedName = obj["*"];
In your case... to get to your object, you can do this query in both cases. To collect all links returned from the query:
var allLinks =
from page in response.SelectToken("query.pages").Values()
from link in page["langlinks"]
select (string)link["*"];

Categories

Resources