Mapping JSON from Yahoo! Finance API to C# objects [duplicate] - c#

This question already has answers here:
Deserialize JSON data with C#
(4 answers)
Closed 1 year ago.
I am a student working on a project. I am trying to use the Yahoo! Finance API as a source for my data https://www.yahoofinanceapi.com . I can use HttpWebRequests to call the API and get the "OK" code, see the code below on how I did it:
string BaseURL = "https://yfapi.net/v6/finance/quote?symbols=AAPL";
string addSymbol = "%2C";
string URL = BaseURL;
foreach (string stock in stocks)
{
URL += addSymbol + stock;
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Headers.Add("X-API-KEY", "[My API key]");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine(response.ContentType);
Console.WriteLine(response.StatusCode);
response.ContentType gives back "application/json".
response.StatusCode gives back "OK".
Since the response is a JSON I tried to parse it into a string using .ToString() but this obviously doesn't work. When I print it, it just says "System.Net.HttpWebResponse" instead of the showing the actual data in the JSON.
After that I tried to deserialize it using newtonsoft
Results result = JsonConvert.DeserializeObject<Results>(request.GetResponse().ToString());
where Results is a class I made where there is a list of stocks, Stock is also a class I made with some variables in it with the same names of variables in the JSON response.
I got a JSON response from PostMan when I tested the API, opened the response to see what kind of data it contained.
When I ran my code I got the following error message:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: S. Path '', line 0, position 0.'
This was as far as I got, I tested a few other methods trying to get this working but this one worked the "best".
My biggest issue at the moment is mapping the response into a c# object.
Anything that can help me understand is appreciated :D

You're trying to serialise the HttpWebResponse object into Results, which means deserialisation won't work.
The data is still wrapped & won't be in the format of the Results object.
The GetResponseStream() method can be used to get the contents of the HTTP response as a stream, which can then be deserialised directly, in this case, using Json.NET.
Replace this section:
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine(response.ContentType);
Console.WriteLine(response.StatusCode);
With this:
var serializer = new JsonSerializer();
using (var response = (HttpWebResponse)request.GetResponse())
{
var encoding = Encoding.GetEncoding(response.CharacterSet);
using var responseStream = response.GetResponseStream();
using var reader = new StreamReader(responseStream, encoding);
using (var jsonTextReader = new JsonTextReader(reader))
{
Console.WriteLine(response.ContentType);
Console.WriteLine(response.StatusCode);
Results result = serializer.Deserialize<Results>(jsonTextReader);
}
}
Alternatively, a much better solution if you're using .NET 4.5 <= would be to use HttpClient like below:
private static readonly HttpClient httpClient = new HttpClient();
...
string BaseURL = "https://yfapi.net/v6/finance/quote?symbols=AAPL";
string addSymbol = "%2C";
string URL = BaseURL;
foreach(string stock in stocks) {
URL += addSymbol + stock;
}
client.DefaultRequestHeaders.Add("X-API-KEY", "[My API key]");
var data = await httpClient.GetStringAsync(address);
Results result = JsonConvert.DeserializeObject<Results>(data);

Related

Limiting a JSON string response from an API to select attributes

Currently, I am using a [WebMethod] to call an API and get the response as a JSON string.
public string GetFloodData()
{ ...
WebRequest requestObj = WebRequest.Create(url);
requestObj.Method = "GET";
requestObj.ContentType = "application/json";
responseObj = (HttpWebResponse)requestObj.GetResponse();
using (Stream stream = responseObj.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresult = sr.ReadToEnd();
sr.Close();
}
return strresult;
...
}
When I call GetFloodData(), I get the following response in the browser:
<string xmlns="http://tempuri.org/">
{"ListEvents":
[{"EventID":1,"EventName":"Debby2000","State":"PR","EventType":"Tropical or
Extratropical","Days":5,"LSTStart":"\/Date(9666432000000000)\/",
"LSTEnd":"\/Dat e(967075200000-0000)\/"}, {...}....]}
At this point (before I parse it as a formal JSON Object), I just want to eliminate the stuff I don't want ("Days","LSTStart", and "LSTEnd") and keep what I want. How would I limit what attributes are returned in my response?
You can de-serialise it with a class, and in that class, you can write only the variables you do want to keep. Although, keep the structure of the Json and the class as same. Variables can be missing, but the structure should be the same

Substring a HTTP Response into a Variable [C# Winforms]

Im trying to get a cryptocurrency last price value from a HTTP API:
The following piece of code:
// Create the web request
HttpWebRequest request =
WebRequest.Create("APISITE") as
HttpWebRequest;
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Console application output
currentXRPPrice.Text = (reader.ReadToEnd());
}
Gives me the following response which is correct:
{"high": "1.15600", "last": "1.08269", "timestamp": "1518697359", "bid": "1.08034", "vwap": "1.09634", "volume": "40858340.75727354", "low": "1.03051", "ask": "1.08269", "open": "1.13489"}
What I want is just the value of "last" which is "1.08269".
I have tried using this post: [link] (Remove characters after specific character in string, then remove substring?)
which has worked wonders for me on previous projects. But I cant seem to figure out where I am going wrong.
Iv tried below to get the value of "last" but its completely wrong, I have tried many of the different combinations to get it right but its not working to show me just the value for "Last".
response = currentXRPPrice.Text;
response = response.Remove(response.LastIndexOf(":") + 1);
profitLossText.Text = response; //Still wrong tried 4 combinations none work.
Thanks for any help!
You need to install Newtonsoft.Json from Nuget packages and use Parse method from JObject:
var lastValue = JObject.Parse(currentXRPPrice.Text).SelectToken("last").ToString();
First of all, if you have Json string, you can define a class which represent this object and then you just deserialize this string to object using generic method.
var jsonString = currentXRPPrice.Text;
var deserializedResponse = JsonConvert.DeserializeObject<ReponseType>(jsonString);
var lastValue = deserializedResponse.Last;
public class ReponseType
{
...
public float Last { get; set; }
...
}
You can do it by Regex too:
var lastValue = Regex.Match(jsonString, #"last\": \"(\\d+\\.\\d+)"").Groups[0];

Can't access Web of Trust (WoT) API w/ JSON.Net

I'm new to JSON & am using VS 2013/C#. Here's the code for the request & response. Pretty straightforward, no?
Request request = new Request();
//request.hosts = ListOfURLs();
request.hosts = "www.cnn.com/www.cisco.com/www.microsoft.com/";
request.callback = "process";
request.key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string output = JsonConvert.SerializeObject(request);
//string test = "hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
try
{
var httpWebRequest = (HttpWebRequest) WebRequest.Create("http://api.mywot.com/0.4/public_link_json2?);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = output;
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
}
}
catch (WebException e)
{
MessageBox.Show(e.ToString());
}
//response = true.
//no response = false
return true;
}
When I run this, I get a 405 error indicating method not allowed.
It seems to me that there are at least two possible problems here: (1) The WoT API (www.mywot.com/wiki/API) requires a GET request w/ a body, & httpWebRequest doesn't allow a GET in the httpWebRequest.Method; or (2) the serialized string isn't serialized properly.
NOTE: In the following I've had to remove the leading "http://" since I don't have enough rep to post more than 2 links.
It should look like:
api.mywot.com/0.4/public_link_json2?hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxx
but instead looks like:
api.mywot.com/0.4/public_link_json2?{"hosts":"www.cnn.com/www.cisco.com/www.microsoft.com/","callback":"process","key":"xxxxxxxxxxxxxxxxxxx"}.
If I browse to:api.mywot.com/0.4/public_link_json2?hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxx; I get the expected response.
If I browse to: api.mywot.com/0.4/public_link_json2?{"hosts":"www.cnn.com/www.cisco.com/www.microsoft.com/","callback":"process","key":"xxxxxxxxxxxxxxxxxxx"}; I get a 403 denied error.
If I hardcode the request & send as a GET like below:
var httpWebRequest = (HttpWebRequest) WebRequest.Create("api.mywot.com/0.4/public_link_json2? + "test"); it also works as expected.
I'd appreciate any help w/ this & hope I've made the problem clear. Thx.
Looks to me like the problem is that you are sending JSON in the URL. According to the API doc that you referenced, the API is expecting regular URL encoded parameters (not JSON), and it will return JSON to you in the body of the response:
Requests
The API consists of a number of interfaces, all of which are called using normal HTTP GET requests to api.mywot.com and return a response in XML or JSON format if successful. HTTP status codes are used for returning error information and parameters are passed using standard URL conventions. The request format is as follows:
http://api.mywot.com/version/interface?param1=value1&param2=value2
You should not be serializing your request; you should be deserializing the response. All of your tests above bear this out.

using dynamic keyword when parse JSON

I'm newbie to using the dynamic keyword in C#. It seems simple enough, but I can't seem to use it effectively.
I see this example from Facebook:
var client = new FacebookClient();
dynamic me = client.Get("totten");
string firstname = me.first_name;
it works fine, but if you look at me in a debugger, then you can see that client.Get() returns simple JSON. The same it's said in Facebook documentation:
The result of this request is a dynamic object containing various
properties such as first_name, last_name, user name, etc. You can see
the values of this request by browsing to
http://graph.facebook.com/totten in your web browser. The JSON result
is shown below.
I want to do the same dodge with returned JSON from Foursquare:
private static string GetReturnedUrlFromHttp(string url)
{
HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
webRequest.Timeout = 10000;
webRequest.Method = "GET";
WebResponse response = webRequest.GetResponse();
string responseStr = String.Empty;
using (var stream = response.GetResponseStream())
{
var r = new StreamReader(stream);
responseStr = r.ReadToEnd();
}
return responseStr;
}
public static void FillDataFromFoursquareUsingDynamic()
{
string foursquare_url_detail = "https://api.foursquare.com/v2/venues/4b80718df964a520e57230e3?locale=en&client_id=XXX&client_secret=YYY&v=10102013";
dynamic responseStr = GetReturnedUrlFromHttp(foursquare_url_detail);
var response = responseStr.response;
}
I got the following error:
'string' does not contain a definition for 'response'
Why am I getting this error and is it possible to 'parse' any JSON string like in Facebook?
FacebookClient.Get doesn't really return the JSON string. Instead it parses the string into a dynamic object with properties matching the names of the values in the JSON string.
Using dynamic doesn't magically turn a string into an object with the properties defined in the string. Instead, you need to first parse the string with the help of a JSON library like JSON.NET.

Receiving Json in HttpPost - ASP.net

I've set up a page to do an HTTP Post with a Json serialized generic list, to a different page in ASP.net. When it goes to the new page though, I can't seem to find the body of the HTTP Post.
This is the method for the post:
public static void SendHttpPost(string json)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:57102/Post.aspx");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
}
Although this is the first time I've done this, I presumed you would be able to access the Json using Request.Form or similar, but Request.Form is empty. I've had a good look at the VS degugger and can't see it anywhere in the Request object, but the content length is 68000 bytes, so I'm sure it's in there somewhere!
Can anyone point me in the right direction please? Many thanks
You can retrieve the Request Body using Request.InputStream as shown here : gist.github.com/leggetter/769688 !

Categories

Resources