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.
Related
To keep it short:
Following method calls a method from the WebUntisAPI (here we look for all rooms):
(this.sessionID has stored the session ID i requested in a authenticationmethod before)
public void getRooms()
{
client.AddHandler(new JsonDeserializer(), "application/json-rpc");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-type", "application/jason");
request.AddJsonBody(new
{
id = this.sessionID,
method = "getRooms",
#params = new {},
jsonrpc = "2.0"
});
var response = this.client.Execute(request);
var deserialized = JsonConvert.DeserializeObject<GetRoomsResponse>(response.Content);
try
{
foreach (GetRoomsResult i in deserialized.res)
{
Console.WriteLine(i.name);
}
}catch(Exception e)
{
Console.WriteLine("Something wrong with deserialization!");
}
}
The Problem is, that the response of the is as followed:
{"jsonrpc":"2.0","id":"030BDA942554038735AE69C94D6B0491","error":{"message":"not authenticated","code":-8520}}
But the fun is not over yet!
If i copy the created json body and put him into postman, with the same key which is in the this.sessionID variable (of course also the same URL) it is working just fine.
If i generate the sessionID outside the programm and hardcode it to the variable it doesn't work as well.
Anybody already worked with the WebUntisAPI and knows why this doesn't work?
I think maybe it has nothing to do with WebUntis but with the way WPF works after compiling. I really don't know.
Thanks for any advice and help,
Fabian
edit:
WebUntisAPI documentation i got/found if you want to read it yourself
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.
JSON that I get from the application has date field in format like
"Date":"2016-04-22T00:00:00.000+0000"
And when it gets deserialized by the RestSharp, the date becomes equal to
"04/22/2016 03:00:00"
After brief investigation, I understood that RestSharp automatically applies UTC offset for the parsed date. But in my case I need to get what is stored in JSON honestly.
Is there any way for RestSharp to disable auto applying UTC offset for date fields in JSON?
Thanks in advance
RestSharp will likely use the .Net DateTime methods to parse the string into a DateTime type. The DateTime.Parse method will convert the input string into the timezone read from Regional and Language options from the Control Panel. If you don't want that to happen, the Parse function should be supplied with a different Culture setting (e.g. InvariantCulture). If you don't have control over the RestSharp code, you could set a thread culture before calling the RestSharp method, use System.Threading.Thread.CurrentThread.CurrentCulture. This won't work if RestSharp runs on a different thread. In that case you could convert the input string by doing your own DateTime conversion negating the local machine timezone difference. Then you can then convert it to the proper string format again and use that as input to RestSharp.
It seems that the UTC JSON DateTime string "2016-04-22T00:00:00.000+0000" gets converted to a local DateTime object "04/22/2016 03:00:00".
One way out is to specify the DateTimeKind for each of you DateTime objects as Local and then convert them back to UTC. See this:
The better way out is to use Json.Net for serialization, under the hood. I have used it liked this:
private class MyWrappedRestClient : RestClient
{
public MyWrappedRestClient(string baseUrl) : base(baseUrl) { }
private IRestResponse<T> Deserialize<T>(IRestRequest request, IRestResponse rawResponse)
{
request.OnBeforeDeserialization(rawResponse);
var restResponse = (IRestResponse<T>)new RestResponse<T>();
try
{
restResponse = rawResponse.ToAsyncResponse<T>();
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));
}
}
I am not sure if the issue I am having is related to the way I'm using Task or if I am an not using ReadAsAsync correctly. I am following the pattern I found here:
http://blogs.msdn.com/b/henrikn/archive/2012/02/11/httpclient-is-here.aspx
Background:
Object I am deserializing is a POCO. Properties have no attributes. It is just a few value type properties and a couple collection properties. REST service appears to work ok also. When I look at the JSON returned by the service it appears to be OK.
Using Web API 2.1 5.1.2
Problem:
.. is calling HttpResponseMessage.Content.ReadAsAsync(). Sometimes it works (returns an object) and sometimes it doesn't (throws "Thread was being aborted" or returns null). It appears the content property can be read once only and subsequent reads throw errors. See comments in code below.
Related questions:
HttpContent.ReadAsAsync Deserialization issue
Question appears to be similar to mine. Answer indicates a bug but this is over two years old.
Code:
[TestMethod]
public void AddSiteTest()
{
// Use POST to create a resource i.e. insert. Use PUT to update.
Site site = new Site {SiteName = "Test", Active = true, URI="www.test.com" };
Site newSite = null;
client.PostAsJsonAsync<Site>(baseURI + "/Sites/AddSite?securityKey="+ SecurityKey, site).ContinueWith(x =>
{
HttpResponseMessage response = x.Result;
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
try
{
string str = Task.Run(() => response.Content.ReadAsStringAsync()).Result; // yep its json and it is a proprety serialized object
// Method 1 (preferred... ):
//Site siteA = Task.Run(() => response.Content.ReadAsAsync<Site>()).Result; // usuallly throws if content has been read
// Method 2:
Site siteB = response.Content.ReadAsAsync<Site>().Result; // usully returns a valid result (when I dont put a breakpoint on it). Does not deadlock.
// Method 3:
response.Content.ReadAsAsync<Site>().ContinueWith(d =>
{
Site siteC = d.Result; // returns null
});
}
catch (Exception ex)
{
string y = ex.Message;
}
}
});
}
try to use await:
string str = await response.Content.ReadAsStringAsync();
And you have to add async before void in your method.
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.