Good morning! I'm still learning my way around REST API calls and generally processing HTTP requests, so please provide any feedback :)
I'm trying to make a GET call to a web service, which should return a JSON string that's a set of information, which is supposed to be a SQL record returned in a sort of dictionary-like manner.
However, I am having several hiccups and don't know if I'm approach the resolution correctly:
Call web service. Define it as a 'GET' call.
Process the response and read it using a StreamReader.
Using the NewtonSoft JSON method, deserialize the response into a dictionary format. <-- Currently stuck here.
Use dictionary to my liking.
// Call the Web Service
string url = "{URL HERE}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json";
request.ContentLength = 0;
//Dictionary<string, string> dataList = null;
try
{
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var json = reader.ReadToEnd();
//Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
var data = JsonConvert.DeserializeObject<List<KeyValuePair<string, List<KeyValuePair<string, string>>>>>(json);
var dataDictionary = data.ToDictionary(
x => x.Key,
x => x.Value.ToDictionary(y => y.Key, y => y.Value));
//dataList = (Dictionary<string, string>) dataDictionary;
var test = dataDictionary["Key"];
What the JSON string from the call sort of looks like:
"[{\"Number\":4,\"FieldABC\":\"ABC\"}]"
Other solutions I have tried:
Using the data type Dictionary instead.
Various other method calls, like the ones commented out in the code.
Another SO post suggested the ToDictionary() call.
Errors I have run into:
{"Value cannot be null.\r\nParameter name: source"} System.Exception {System.ArgumentNullException}
Cannot convert JSON string to JSON object.
Am I misunderstanding how to process the response from the HTTP request? Or am I confusing / misusing data types? Any help is greatly appreciated!
Update: With all the answers below, the solution ended up being a combination of all of the comments! First, I used json2csharp.com to create the object. Then, using the updated HTTP calls recommended below, I deserialized the JSON into a type Lists so that I got a list of length 1 that I could access my information from. Thanks everyone!
So when I use http://json2csharp.com/ for example to use your JSON, I would get:
public class ClassName
{
public int Number { get; set; }
public string FieldABC { get; set; }
}
Use HttpClient, that makes it easier:
using (var client = new HttpClient())
{
var response = await client.GetAsync(progressUrl);
var yourObject == JsonConvert.DeserializeObject<ClassName>(await response .Content.ReadAsStringAsync());
}
Continue with the rest...
You can also use HttpClientExtensions Class.
Cheers!
First make a POCO which exactly matches the response string. Something like this:
public class MyResponseObject {
public int Number { get; set; }
public string FieldABC { get; set; }
// other properties here
}
Assuming you are sent an array of these objects as [{\"Number\":4,\"FieldABC\":\"ABC\"}] suggests then you can deserialize it using
JsonConvert.DeserializeObject<List<MyResponseObject>>(json);
If it is a more complicated object then you can include additional nested objects in your principal object:
public class MyNestedObject {
public string NestedName { get; set; }
public bool IsEnabled { get; set; }
}
public class MyResponseObject {
public List<MyNestedObject> NestedObjects { get; set; }
}
Once you have a List<MyResponseObject> you may find you don't need a dictionary at all, or if you do you can take advantage of the many Linq Enumerable methods without worrying about JSON.
Use HttpClient instead of HttpWebRequest, as follows:
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await httpClient.GetAsync(url);
var data = await response.Content.ReadAsStringAsync();
Dictionary<string, string> ValueList = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
}
Related
I have created small class
class JsonResponse
{
public string Response { get; set; }
}
Then in my program I send some json data and wait store reply to the following variable
var ResultJSON = Post(uri, values);
while parsing I get
Service Error: Cannot convert object of type 'System.String' to type
'App.someclass+JsonResponse'
using Newtonsoft.Json;
class JsonResponse
{
public string Response { get; set; }
}
class Utility
{
public JsonResponse JsonDeserialisation(string response)
{
TextReader textReader = new StreamReader(response);
JsonTextReader jsonReader = new JsonTextReader(textReader);
return JsonSerializer.CreateDefault().Deserialize<JsonResponse>(jsonReader);
}
}
class Main
{
static void Program()
{
var ResultJSON = "Json String received from post";//Post(uri, values);
var deserialisedJson = Utility.JsonDeserialisation(ResultJSON);
}
}
Add newtonSoft.json nuget package to project
try
var Result = new JavaScriptSerializer().Deserialize<JsonResponse>(ResultJSON.**Response**);
looks to me that you are trying to deserialize from an object rather than the string response
Try this, may give your JSON file to result variable.
var result = Convert.ToString(ResultJSON);
Try using using newtonsoft.json downloadable here or use the nuget package.
It has a function that does exactly what you want. Expecting the result of the Post is in string format of course.
var result = JsonConvert.DeserializeObject<JsonResponse>(ResultJSON);
Your JsonResponse class must look exacly the same as the json your getting. So make sure if you get more data in the json that you want to save in the class the names are the same.
If you have anymore questions feel free to ask.
Hey I am having a weird issue I can't figure out. Basically I am trying to make a simple httpClient post request but I keep getting an "Invalid json primitive:." I have checked on https://jsonlint.com/ and it says this is valid json but my application states otherwise. Any info would be greatly appreciated?
string test = "{\"CurrentUser\":null,\"Stacktrace\":\"System.UnhandledExceptionEventArgs\",\"OtherData\":null,\"UserInput\":\"\",\"TimeStamp\":\"2017-10-10T16:48:58.606512-04:00\"}"
HttpContent httpContent = new StringContent(test);
await httpClient.PostAsync("/api/logException", httpContent);
And the client is initialized like:
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(this.serverURL);
httpClient.Timeout = TimeSpan.FromSeconds(400);
Instead of writing the JSON format on your own (which is prone to error), how about you simply create an object and serialize it to JSON. Have c# do the heavy lifting. First create a class like:
public class Model
{
public string CurrentUser { get; set; } = null;
public string Stacktrace { get; set; } = "System.UnhandledExceptionEventArgs";
public string UserInput { get; set; } = String.Empty;
public string OtherData { get; set; } = null;
public string TimeStamp { get; set; } = "2017-10-10T16:48:58.606512-04:00";
}
Then initialize an object of this class and simply use JavaScriptSerializer to serialize it into json:
Model md = new Model();
System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = ser.Serialize(md);
The result will be in json:
{"CurrentUser":null,"Stacktrace":"System.UnhandledExceptionEventArgs","UserInput":"","OtherData":null,"TimeStamp":"2017-10-10T16:48:58.606512-04:00"}
I'm no expert, but since nobody else has responded, perhaps you just need to set the content type to JSON?
HttpContent httpContent = new StringContent(test, Encoding.UTF8, "application/json");
See POSTing JsonObject With HttpClient From Web API
Try to String.Replace("\", string.Empty) to your json. Perhaps this will work.
Hey thanks for the answers. You are all correct and I appreciate the help. The issue was in the end not actually json. Basically this error was propagating and actually appearing twice after I thinking it was handled. So where I thought it was telling me invalid json existed (where it was breaking) was actually it repeating the same error message from further up the code.
Thanks again.
On my server I tried this test code:
[AllowAnonymous]
[Route("GetX")]
public IQueryable<Phrase> GetX()
{
var phrases = new List<PhraseX>
{
new PhraseX() {Keyword="abc", Translation1="abc1", Translation2="abc2" },
new PhraseX() {Keyword="def", Translation1="def1", Translation2="def2" },
new PhraseX() {Keyword="ghi", Translation1="ghi1", Translation2="ghi2" },
};
return db.Phrases;
}
Here's what I have so far on the client which is a terminal application:
var request = HttpWebRequest.Create("http://www.example.com/api/Phrase/GetX");
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
I am getting the expected data back but now I am not sure how can I get the data that's returned as json back into a list? Any suggestions on how I could do this?
You need to deserialize the JSON to C# objects.
These links will help you:
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
http://www.newtonsoft.com/json/help/html/deserializeobject.htm
This is how you may do it:
string jsonStr = "[{Keyword:\"abc\", Translation1:\"abc1\", Translation2:\"abc2\" },{Keyword:\"def\", Translation1:\"def1\", Translation2:\"def2\" },{Keyword:\"ghi\", Translation1:\"ghi1\", Translation2:\"ghi2\" }]";
JavaScriptSerializer jss = new JavaScriptSerializer();
List<PhraseX> phrases = jss.Deserialize<List<PhraseX>>(jsonStr);
where PhraseX is a class-
public class PhraseX
{
public string Keyword { get; set; }
public string Translation1 { get; set; }
public string Translation2 { get; set; }
}
Note: You will find JavaScriptSerializer class in System.Web.Extensions.dll
You may also use JSON.NET for same.
Hope it helps.
You can deserialize the JSON to C# objects, as stated in the previous answer.
Using Json.NET (Newtonsoft.Json namespace), you can pass your JSON data to the JsonConvert.DeserializeObject<T>(json_data) method, with T being the data type the JSON should be deserialized into and json_data obviously being the JSON data you have received. You can obviously also use the built-in JavaScriptSerializer if you don't want to introduce a third-party dependency to your solution.
Visual Studio gives you a very easy way to create the C# classes for your JSON, have a look at my answers here and here.
I need to call this method in MVC controller and pass the UpdateRequest object as json format. how I can do that?
[HttpPost]
[Route("updatecertificate")]
public void updatecertificate([FromBody] UpdateRequest certificatereviewed)
{
loansRepository.updatecertificate(certificatereviewed.Id, certificatereviewed.CertificateReview);
}
and this is the input class:
public class UpdateRequest {
public int Id { get; set; }
public bool CertificateReview { get; set;}
}
this is how I call and send separate variable but now I like to send the class object in json format.
private async Task UpdateFundingCertificateReviewed(int id, bool fundingCertificateReviewed)
{
await httpClient.PostAsync(string.Format("{0}/{1}", LoanApiBaseUrlValue, updatecertificate),null);
}
I personally like Newtonsoft.Json to serialize the object.
private async Task UpdateFundingCertificateReviewed
(int id, bool fundingCertificateReviewed)
{
using (var client = new HttpClient())
{
var url = string.Format("{0}/{1}", LoanApiBaseUrlValue, updatecertificate);
var updateRequest = new UpdateRequest { Id = 1, CertificateReview = true};
var data = JsonConvert.SerializeObject(updateRequest);
await client.PostAsync(url, data);
}
}
FYI: Async without return is not a good practice. However, it is out of the original question.
If you want to transform an object into a JSON string, see this question: Turn C# object into a JSON string in .NET 4
var json = new JavaScriptSerializer().Serialize(obj);
Is this what you are after or do you want to know how to construct the http request with a JSON object in the body?
your questionis not very clear, what is the outcome that you expect ?
If you want to POST an request with JSON body you can check the #Win comment,
however if you want to make an Response from the Api to the MVC project you should do a bit more steps tough. :))
How do I correctly deserialise the results of this call (you can click to see output):
https://bitpay.com/api/rates
I'm using a POCO object like this:
public class BitpayPrice
{
public string code { get; set; }
public string name { get; set; }
public double rate { get; set; }
}
And I'm calling the API like so:
var client = new RestClient();
client.BaseUrl = "https://bitpay.com";
var request = new RestRequest("/api/rates", Method.GET);
var response = client.Execute<BitpayPrice[]>(request);
Now, I know that the call to execute is wrong, but how do I un-wrongify it? I'd like to get back an array of BitcoinPrice objects.
RestSharp doesn't support deserializing into array, the best you can get is a List<>:
var response = client.Execute<List<BitpayPrice>>(request);
The reason is that types that you can deserialize to are required to have public parameterless constructor (for performance reasons mostly).