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
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;
}
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.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);
}
}
}
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();
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["*"];