read JSON object gives error "int expected" [duplicate] - c#

I am using the guardian API to try and retrieve stories but keep receiving an exception. The string of json contains the below json, however I can't access the body using LINQ.
Here it is:
{
"response":{
"status":"ok",
"userTier":"approved",
"total":1,
"startIndex":1,
"pageSize":10,
"currentPage":1,
"pages":1,
"orderBy":"newest",
"results":[{
"id":"sustainable-business/sustainable-finance-where-next-open-thread",
"sectionId":"sustainable-business",
"sectionName":"Guardian Sustainable Business",
"webPublicationDate":"2014-02-13T13:27:00Z",
"webTitle":"Where next for sustainable finance? - open thread",
"webUrl":"http://www.theguardian.com/sustainable-business/sustainable-finance-where-next-open-thread",
"apiUrl":"http://content.guardianapis.com/sustainable-business/sustainable-finance-where-next-open-thread",
"fields":{
"body":"<img src=\"http://hits.theguardian.com/b/ss/guardiangu-api/1/H.20.3/98867?ns=guardian&pageName=Where+next+for+sustainable+finance%3F+-+open+thread+Article+2043222&ch=Guardian+Sustainable+Business&c2=461773&c4=MIC%3A+Finance+%28GSB%29%2CMIC%3A+Guardian+Sustainable+Business%2CPRO%3A+Sustainability+%28Guardian+Professional%29&c3=theguardian.com&c6=Laura+Paddison&c7=14-Feb-13&c8=2043222&c9=Article\" width=\"1\" height=\"1\" />..."
}
}]
}
}
I have tried every thing including this:
string story = (string)ja["response"]["results"]["fields"]["body"];
Update:
public partial class Story : PhoneApplicationPage
{
string url;
string jsonData;
// Http used so the json can be retrived via the get async methods
HttpClient webClient = new HttpClient();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.ContainsKey("key"))
{
string encodedValue = NavigationContext.QueryString["key"];
url = Uri.UnescapeDataString(encodedValue);
textBox.Text = url;
guardianPanorama();
}
}
private async void guardianPanorama()
{
try
{
HttpResponseMessage Result = await webClient.GetAsync(url);
// This takes the http response content and is turned into a string
jsonData = await Result.Content.ReadAsStringAsync();
JObject ja = JObject.Parse(jsonData);
// This takes the current bitcoin price and formats it so there is the correct amount of decimal places
string story = (string)ja["response"]["results"]["fields"]["body"];
// It then gets added to the textbox
textBox.Text = story;
}
catch (Exception errors)
{
MessageBox.Show("There has been a error with the Guardian API");
Console.WriteLine("An error occured:" + errors);
}
}
}
Exception:
System.ArgumentException: Accessed JArray values with invalid key value: "fields". Array position index expected.
at Newtonsoft.Json.Linq.JArray.get_Item(Object key)

If you replace
// This takes the current bitcoin price and formats it so there is the correct amount of decimal places
string story = (string)ja["response"]["results"]["fields"]["body"];
with
// This takes the current bitcoin price and formats it so there is the correct amount of decimal places
string story = (string)ja["response"]["results"][0]["fields"]["body"];
that should work for your example. Note the square bracket after results in the example you provided, that indicates an array that should be accounted for in your access code.

Related

Json deserializer gets 'Unexpected character encountered while parsing value: S. Path '', line 0, position 0.'

I am trying to make CRUD functionality for the table Recipe. Everything works fine in the API, however, I am stuck at the Update part inside the MVC. Basically, when trying to access the view meant for updating, all of the fields should be already filled, compared to when I am creating a recipe from scratch.
public ActionResult CreateOrEdit(int id = 0)
{
if (id==0)
return View(new Recipe());
else
{
HttpResponseMessage response = GlobalVariablesUpdate.clientUp.GetAsync(id.ToString()).Result;
var temp = response.Content.ReadAsStringAsync().Result;
return View(JsonConvert.DeserializeObject<IList<Recipe>>(response.ToString()));
}
}
The code inside the else{}is meant to fill all the values after reading the content. Unfortunately, on line
return View(JsonConvert.DeserializeObject<IList<Recipe>>(response.ToString()));
I am getting the following error
'Unexpected character encountered while parsing value: S. Path '',
line 0, position 0.'
The temp variable's content looks like this:
"[{\"id\":5002,\"name\":\"Test Recipe\",\"recipeLink\":\"testlink\",\"category1Id\":7757,\"category2Id\":7758,\"category3Id\":7759,\"category4Id\":7760,\"recipeById\":1,\"totalTime\":30,\"totalTimeUnitId\":1,\"activeTime\":20,\"activeTimeUnitId\":1,\"instructions\":\"Test Instructions\",\"sourceKey\":\"Test SK\",\"recipeBy\":\"TestPerson\",\"insertedAtUtc\":\"2019-09-04T12:18:48.0466667\",\"isVerified\":1,\"numPersons\":5}]"
I assume the root of this problem is that my response variable has these backslashes, hence the unexpected character encounter. How can I get rid of this?
EDIT
.Replace(#"\", " ") doesn't work, so I assume that the backslash might not actually be the issue?
You are deserializing response.ToString(), but you should be deserializing temp:
var recipes = JsonConvert.DeserializeObject<IList<Recipe>>(temp);
return View(recipes);
Sidenotes: you should make your method async, to avoid deadlocks, and dispose your response:
public async Task<ActionResult> CreateOrEdit(int id = 0)
{
if (id==0)
{
return View(new Recipe());
}
using (var response = await GlobalVariablesUpdate.clientUp.GetAsync(id.ToString())
{
var temp = await response.Content.ReadAsStringAsync();
var recipes = JsonConvert.DeserializeObject<IList<Recipe>>(temp);
return View(recipes);
}
}

An exception of type 'System.NullReferenceException' occurred in UWP-Weather-App.exe but was not handled in user code

I've been following a tutorial of a UWP Weather application that uses an API key.
I get a System.NullReferenceException.
This is the method it happens in, at the line that begins with RootObject:
namespace UWP_Weather_App
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
RootObject myWeather = await OpenWeatherMapProxy.GetWeather(20.0, 30.0);
ResultTextBlock.Text = myWeather.name + " - " + myWeather.main.temp + " - " + myWeather.weather[0].description;
}
}
}
According to your description, I'd suppose you are following this UWP Weather tutorial. I used your code with this tutorial's source code and reproduced your issue.
The System.NullReferenceException error occurred at the line ResultTextBlock.Text = myWeather.name + " - " + myWeather.main.temp + " - " + myWeather.weather[0].description;
This is because the URL you've used in GetWeather method is not right. The result returned by this URL doesn't contain weather information and when it is deserialized to RootObject, most properties will be null.
To retrieve current weather data by geographic coordinates, we can use following API:
api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}
And starting from 9 October 2015 this API requires a valid APPID for access. For more info, please see Call current weather data for one location and How to use API key in API call.
So we can change GetWeather method like following to fix this error.
public async static Task<RootObject> GetWeather(double lat, double lon)
{
var http = new HttpClient();
var response = await http.GetAsync($"http://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={APIKEY}&units=metric");
var result = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<RootObject>(result);
return data;
}
Please note that I tried with your API key, but I got 401 Invalid API key error, so please make sure you are using the right key. And also, we need to change Main.pressure and Wind.deg's type to double as their value are not int. If we don't change the type, we may get Newtonsoft.Json.JsonReaderException while deserialization.

cannot return value from async method in view

I'm trying to return value from async html helper but it is giving following string instead of desired values.
"System.Threading.Tasks.Task+WhenAllPromise`1[System.Decimal]"
Method:
public async static Task<decimal> CalculateCurrency(this HtmlHelper helper, decimal amount, string from, string country)
{
if (await getValue(country))
{
string fromCurrency = string.IsNullOrEmpty(from) ? "USD" : from;
string toCurrency = country;
WebClient client = new WebClient();
string url = string.Format("http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={0}{1}=X", fromCurrency.ToUpperInvariant(), toCurrency.ToUpperInvariant());
Stream response = await client.OpenReadTaskAsync(url);
StreamReader reader = new StreamReader(response);
string yahooResponse = await reader.ReadLineAsync();
response.Close();
if (!string.IsNullOrWhiteSpace(yahooResponse))
{
string[] values = Regex.Split(yahooResponse, ",");
if (values.Length > 0)
{
decimal rate = System.Convert.ToDecimal(values[1]);
string res = string.Format("{0:0.00}", rate * amount);
return decimal.Parse(res);
}
}
return decimal.Zero;
}
return decimal.Zero;
}
Call HTML Helper:
#Html.CalculateCurrency(22, "USD", "EUR")
Views don't support asynchronous methods. So as result you get result of default .ToString() function for type of result which indeed returns just type name.
Options:
move code to controller and call in from asynchronous top level (non-child) action with await. Pass data to view via model or ViewBag
convert to real synchronous code if you must call it from the view or child action
if not possible try .Result, but watch out for deadlocks. See await vs Task.Wait - Deadlock? for details/links.
Note: moving async code to child action will not help.

Accessed JArray values with invalid key value: "fields". Array position index expected

I am using the guardian API to try and retrieve stories but keep receiving an exception. The string of json contains the below json, however I can't access the body using LINQ.
Here it is:
{
"response":{
"status":"ok",
"userTier":"approved",
"total":1,
"startIndex":1,
"pageSize":10,
"currentPage":1,
"pages":1,
"orderBy":"newest",
"results":[{
"id":"sustainable-business/sustainable-finance-where-next-open-thread",
"sectionId":"sustainable-business",
"sectionName":"Guardian Sustainable Business",
"webPublicationDate":"2014-02-13T13:27:00Z",
"webTitle":"Where next for sustainable finance? - open thread",
"webUrl":"http://www.theguardian.com/sustainable-business/sustainable-finance-where-next-open-thread",
"apiUrl":"http://content.guardianapis.com/sustainable-business/sustainable-finance-where-next-open-thread",
"fields":{
"body":"<img src=\"http://hits.theguardian.com/b/ss/guardiangu-api/1/H.20.3/98867?ns=guardian&pageName=Where+next+for+sustainable+finance%3F+-+open+thread+Article+2043222&ch=Guardian+Sustainable+Business&c2=461773&c4=MIC%3A+Finance+%28GSB%29%2CMIC%3A+Guardian+Sustainable+Business%2CPRO%3A+Sustainability+%28Guardian+Professional%29&c3=theguardian.com&c6=Laura+Paddison&c7=14-Feb-13&c8=2043222&c9=Article\" width=\"1\" height=\"1\" />..."
}
}]
}
}
I have tried every thing including this:
string story = (string)ja["response"]["results"]["fields"]["body"];
Update:
public partial class Story : PhoneApplicationPage
{
string url;
string jsonData;
// Http used so the json can be retrived via the get async methods
HttpClient webClient = new HttpClient();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.ContainsKey("key"))
{
string encodedValue = NavigationContext.QueryString["key"];
url = Uri.UnescapeDataString(encodedValue);
textBox.Text = url;
guardianPanorama();
}
}
private async void guardianPanorama()
{
try
{
HttpResponseMessage Result = await webClient.GetAsync(url);
// This takes the http response content and is turned into a string
jsonData = await Result.Content.ReadAsStringAsync();
JObject ja = JObject.Parse(jsonData);
// This takes the current bitcoin price and formats it so there is the correct amount of decimal places
string story = (string)ja["response"]["results"]["fields"]["body"];
// It then gets added to the textbox
textBox.Text = story;
}
catch (Exception errors)
{
MessageBox.Show("There has been a error with the Guardian API");
Console.WriteLine("An error occured:" + errors);
}
}
}
Exception:
System.ArgumentException: Accessed JArray values with invalid key value: "fields". Array position index expected.
at Newtonsoft.Json.Linq.JArray.get_Item(Object key)
If you replace
// This takes the current bitcoin price and formats it so there is the correct amount of decimal places
string story = (string)ja["response"]["results"]["fields"]["body"];
with
// This takes the current bitcoin price and formats it so there is the correct amount of decimal places
string story = (string)ja["response"]["results"][0]["fields"]["body"];
that should work for your example. Note the square bracket after results in the example you provided, that indicates an array that should be accounted for in your access code.

Why is RestSharp deserializing two dates differently?

I have a rest call that returns this (using Advance Rest Client in Chrome to do testing):
MyObject: [22]
0: {
ID: "123456"
UTC1: "2013-04-19T03:12:32Z"
UTC2: "2013-04-19T03:12:36.994Z"
}
The code that grabs the response and serializes it to an object looks like this:
IRestResponse<List<MyObject>> response = client.Execute<List<MyObject>>(request);
When I look at the response object one of the dates is wrong. If I inspect it or use the objects in any way I get this:
UTC1: 4/19/2013 3:12
UTC2: 4/18/2013 9:12:36 PM <--CONVERTED!!
I need both to be serialized as the time that is returned in the response, not converted from UTC/GMT to local time. As you can see above one value keeps its UTC value while the other gets converted to my timezone. I figured that both were being run through the Convert.DateTime function but if I do that with the strings both values come out as converted to local time. I realize that one fo the original values (the one that is getting converted) doesn't exactly obey ISO 8601 format (too much precision); unfortunately that is the data I have to work with for now.
Can anyone tell me how to force RestSharp to make sure both dates are in UTC?
Use Json.NET to do the deserialization instead of the built in RestSharp deserializer.
response = client.Execute(request);
var myObjects = JsonConvert.Deserialize<List<MyObject>>(response)
Posting this for convenience:
private class CustomRestClient : RestClient
{
public CustomRestClient(string baseUrl) : base(baseUrl) { }
private IRestResponse<T> Deserialize<T>(IRestRequest request, IRestResponse raw)
{
request.OnBeforeDeserialization(raw);
var restResponse = (IRestResponse<T>)new RestResponse<T>();
try
{
restResponse = ResponseExtensions.toAsyncResponse<T>(raw);
restResponse.Request = request;
if (restResponse.ErrorException == null)
{
restResponse.Data = JsonConvert.DeserializeObject<T>(restResponse.Content);
}
}
catch (Exception ex)
{
restResponse.ResponseStatus = ResponseStatus.Error;
restResponse.ErrorMessage = ex.Message;
restResponse.ErrorException = ex;
}
return restResponse;
}
public override IRestResponse<T> Execute<T>(IRestRequest request)
{
return Deserialize<T>(request, Execute(request));
}
}
This is a simple code I put together, it just overrides Execute<T> and uses Json.net under the hood.

Categories