Error while Deserializing JSON output - c#

I am getting the following error at dynamic jsonText = JsonConvert.DeserializeObject(json);
ERROR
Unexpected character encountered while parsing value: <. Path '', line
0, position 0.
CODE
string api = "https://api.linkedin.com/v1/people/~:(id,first-name,formatted-name,email-address)";
using (var webClient = new WebClient())
{
webClient.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);
var json = webClient.DownloadString(api );
dynamic jsonText = JsonConvert.DeserializeObject(json);
}

I think it is necessary to specify that you want the result in json, otherwise some web services returns the data in xml
webClient.Headers.Add(System.Net.HttpRequestHeader.Accept, "application/json");
//also the encoding if need
webClient.Headers.Add(System.Net.HttpRequestHeader.AcceptEncoding, "utf-8");
but in linkedin you must use
webClient.Headers.Add("x-li-format", "json");
More info here
https://developer.linkedin.com/docs/rest-api

Related

Rest Client adding json body return MESSAGE_NOT_READABLE

I am trying to use RestClient in C#
var client = new RestClient(signUrl);
var request = new RestRequest(signUrl, Method.Put);
How can I add the following JSON to the request Body
{
"device_configuration_general": {
"id": "fffc16e2-2cf3-40f6-92df-a5b65e617b1c"
}
}
I've tried
var body = "{\"device_configuration_general\": {\"id\": \"f60c3043-cedc-4d2e-b713-5c5dce842dc4}}"
request.AddBody(body);
RestResponse response = await client.ExecuteAsync(request);
but getting
"{\"code\":\"MESSAGE_NOT_READABLE\",\"message\":\"JSON parse error: Unexpected end-of-input in VALUE_STRING\",\"serviceName\":\"Device Service\",\"traceId\":\"adf3a952f0585e7d\",\"environment\":\"dev\",\"details\":null}"
I also tried
var body = "{\"device_configuration_general\": {\"id\": \"e8729ce5-e741-4b17-844e-e129133de49e\",}}"
but getting:
"{\"code\":\"MESSAGE_NOT_READABLE\",\"message\":\"JSON parse error: Unexpected character ('}' (code 125)): was expecting double-quote to start field name\",\"serviceName\":\"Device Service\",\"traceId\":\"55804813c2f97aae\",\"environment\":\"dev\",\"details\":null}"
You can add JSON body to the request body:
request.Parameters.Add(new Parameter() {
ContentType = "application/json",
Type = ParameterType.RequestBody,
Value = body
});

RestSharp content response returning bad json format

I am using RestSharp library to make requests to an WebApi.
This is how i am doing it:
var client = new RestClient(url);
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", autentication);
RestSharp.IRestResponse response = client.Execute(request);
This works good until here. The issue that i have is that the content of the response is returning like this:
string jsonObject2 = "\"{\\\"status\\\":\\\"success\\\",\\\"entities\\\":[{\\\"bank_code\\\":2,\\\"name\\\":\\\"BANK 02\\\"},{\\\"bank_code\\\":3,\\\"name\\\":\\\"BANCK 03\\\"},{\\\"bank_code\\\":4,\\\"name\\\":\\\"BANCK 04\\\"}]}\"";
The response.content is adding 2 more \ and when i tried to deserialize and it throws an exception that it cannot convert a string to my model.
How can i resolve that the content returns in this format?
string jsonObject = "{\"status\":\"success\",\"entities\":[{\"bank_code\":2,\"name\":\"BANK 02\"},{\"bank_code\":3,\"name\":\"BANK 03\"},{\"bank_code\":4,\"name\":\"BANK 04\"}]}";
This format i can deserialize because of the correct string json format.
It works when i deserialize to string the content that returns the API and then deserialize again the string into the model type that i want.
string jsonData = JsonConvert.DeserializeObject<string>(restResponse.Content);
EntidadResponse data = JsonConvert.DeserializeObject<EntidadResponse>(jsonData);
string result = string.Empty;
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
result = await reader.ReadToEndAsync();
}
return Content(result, "application/json");

Parsing & Filtering JSON data from API into C# application

My goal is to retrieve JSON data from "The virus tracker" API and parse it into a label. This is for my IB personal project so I just started learning c#. Fount this old code and tried fixing it, it worked with basic GET API's but it doesn't work with the one I'm using. (English not my main language)
POSTMAN RESPONSE
{
"results": [
{
"total_cases": 5954607,
"total_recovered": 2622507,
"total_unresolved": 2255875,
"total_deaths": 363208,
"total_new_cases_today": 53700,
"total_new_deaths_today": 1659,
"total_active_cases": 45257,
"total_serious_cases": 2698001,
"total_affected_countries": 213,
"source": {
"url": "https://thevirustracker.com/"
}
}
],
"stat": "ok"
}
C# CODE
//Creating Client connection
RestClient restClient = new RestClient("https://thevirustracker.com/free-api?global=stats");
//Creating request to get data from server
RestRequest restRequest = new RestRequest("total_cases", Method.GET);
// Executing request to server and checking server response to the it
IRestResponse restResponse = restClient.Execute(restRequest);
// Extracting output data from received response
string response = restResponse.Content;
// Parsing JSON content into element-node JObject
var jObject = JObject.Parse(restResponse.Content);
//Extracting Node element using Getvalue method
string cases = jObject.GetValue("total_cases").ToString();
label1.Text = (cases);
ERROR
An unhandled exception of type 'Newtonsoft.Json.JsonReaderException' occurred in Newtonsoft.Json.dll
Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
My final goal with this code is that label1 says "5954607"
Remember that I'm really new to this so if you can explain the changes you made to the code ill really appreciate it.
You're not using RestRequest correctly or initialized the RestClient wrongly.
If that url you used in the RestClient is the whole url then you don't need a "resource" in the RestRequest.
Due to that mistake you got an HTML response indicated by the error
Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
The value of restResponse.Content probably starts with <html and that is not valid JSON.
The Json payload is a bit more complex then you coded for. The results object holds an array with an object that has your stat property.
Putting these fixes together gives you this code.
RestClient restClient = new RestClient("https://thevirustracker.com/free-api?global=stats");
//Creating request to get data from server
RestRequest restRequest = new RestRequest(null, DataFormat.Json);
// Executing request to server and checking server response to the it
IRestResponse restResponse = restClient.Execute(restRequest);
// Extracting output data from received response
string response = restResponse.Content;
// Parsing JSON content into element-node JObject
var jObject = JObject.Parse(restResponse.Content);
//Extracting
// the object has a results property
// that is an array with one item (zero-based)
// on index 0 there is an object
// that has a property total_cases
string cases = (string) jObject["results"][0]["total_cases"];
label1.Text = (cases);

What should `ReadAsAsync<string>` and `ReadAsStringAsync` be used for?

What should HttpContentExtensions.ReadAsAsync<string> and HttpContent.ReadAsStringAsync be used for?
They would seem to do similiar things but work in curious ways. A couple of tests and their outputs are below. In some cases JsonReaderException are thrown, in some cases, the JSON is output but with additional escape characters.
I've ended up using both functions across my code base, but was hoping to align on one if I could understand how they were supposed to work.
//Create data and serialise to JSON
var data = new
{
message = "hello world"
};
string dataAsJson = JsonConvert.SerializeObject(data);
//Create request with data
HttpConfiguration config = new HttpConfiguration();
HttpRequestMessage request = new HttpRequestMessage();
request.SetConfiguration(config);
request.Method = HttpMethod.Post;
request.Content = new StringContent(dataAsJson, Encoding.UTF8, "application/json");
string requestContentT = request.Content.ReadAsAsync<string>().Result; // -> JsonReaderException: Error reading string.Unexpected token: StartObject.Path '', line 1, position 1.
string requestContentS = request.Content.ReadAsStringAsync().Result; // -> "{\"message\":\"hello world\"}"
//Create response from request with same data
HttpResponseMessage responseFromRequest = request.CreateResponse(HttpStatusCode.OK, dataAsJson, "application/json");
string responseFromRequestContentT = responseFromRequest.Content.ReadAsAsync<string>().Result; // -> "{\"message\":\"hello world\"}"
string responseFromRequestContentS = responseFromRequest.Content.ReadAsStringAsync().Result; // -> "\"{\\\"message\\\":\\\"hello world\\\"}\""
//Create a standalone new response
HttpResponseMessage responseNew = new HttpResponseMessage();
responseNew.Content = new StringContent(dataAsJson, Encoding.UTF8, "application/json");
string responseNewContentT = responseNew.Content.ReadAsAsync<string>().Result; // -> JsonReaderException: Error reading string.Unexpected token: StartObject.Path '', line 1, position 1.
string responseNewContentS = responseNew.Content.ReadAsStringAsync().Result; // -> "{\"message\":\"hello world\"}"
ReadAsStringAsync: This is a basic "get me the content as a string" method. It will work on anything you throw at it because it's just strings.
ReadAsAsync<T>: This is meant to be used to deserialise a JSON response into an object. The reason it fails is because the JSON in the return is not a valid JSON representation of a single string. For example, if you serialise a string:
var result = JsonConvert.SerializeObject("hello world");
Console.WriteLine(result);
Output is:
"hello world"
Note how it is surrounded by double quotes. If you try to deserialise any arbitrary JSON directly into a string that isn't in the format "....." it will throw the exception you see because it is expecting the JSON to start with a ".

Moving from standard .NET rest to RestSharp

For the most part, I have managed quite quickly to move my code from standard .NET code to using RestSharp. This has been simple enough for GET processes, but I'm stumped for POST processes
Consider the following
var request = System.Net.WebRequest.Create("https://mytestserver.com/api/usr") as System.Net.HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json;version=1";
request.Headers.Add("Content-Type", "application/json;version=1");
request.Headers.Add("Accepts", "application/json;version=1");
request.Headers.Add("Authorize", "key {key}");
using (var writer = new System.IO.StreamWriter(request.GetRequestStream())) {
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes("{\n \"firstName\": \"Dan\",\n \"lastName\": \"Eccles\",\n \"preferredNumber\": 1,\n \"email\" : \"testuser#example.com\",\n \"password\": \"you cant get the wood\"\n}");
request.ContentLength = byteArray.Length;
writer.Write(byteArray);
writer.Close();
}
string responseContent;
using (var response = request.GetResponse() as System.Net.HttpWebResponse) {
using (var reader = new System.IO.StreamReader(response.GetResponseStream())) {
responseContent = reader.ReadToEnd();
}
This is fairly straight forward to move across, except for the serialisation code. Is there a particular way this has to be done for RestSharp? I've tried creating an object and using
var json = JsonConvert.SerializeObject(user);
restRequest.RequestFormat = DataFormat.Json;
restRequest.AddBody(json);
but the server still comes back with an error.
I'm also currently using JSON.NET for deserialization to an error object when the user passes in bad data. Is there a way I can deserialize to error object based on a single string using RestSharp?
You're close, but you don't need to worry about serialization with RestSharp.
var request = new RestRequest(...);
request.RequestFormat = DataFormat.Json;
request.AddBody(user); // user is of type User (NOT string)
By telling it that the format is JSON, then passing your already-serialized-as-JSON string, RestSharp is actually encoding it again as a string.
So you pass the string: {"firstName":"foo"} and it actually gets sent to the server as a JSON string object: "{\"firstName\":\"foo\"}" (note how your JSON is escaped as a string literal), which is why it's failing.
Note you can also use an anonymous object for the request:
var request = new RestRequest(...);
request.RequestFormat = DataFormat.Json;
request.AddBody(new{
firstName = "Dan",
lastName = "Eccles",
preferredNumber = 1,
// etc..
});
You use the same typed objects with the response (eg, RestSharp deserializes for you):
var response = client.Execute<UserResponse>(request);
// if successful, response.Data is of type UserResponse

Categories