Cannot serialize stream data asp .net core - c#

Trying to deserialize objects from HTTP response.
Response stream returns information in json and I already checked if it is valid in online deserializer.
I got the object class from the API framework so I think all of the properties should be configured for the response.
Code:
var request = new HttpRequestMessage(HttpMethod.Get,
"api_url");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
var reponseString = await response.Content.ReadAsStringAsync();
var data = await JsonSerializer.DeserializeAsync<IEnumerable<Tournament>>(responseStream);
}
else
{
GetBranchesError = true;
}
I see that information in responseString is correct but data objects are always null.
Weird part is that it partially works because it shows how many objects are in the responseStream but all of the object properties are nulls.
Also tried to set the stream position to 0 - didn't help.
Any idea what I am doing wrong to deserialize these objects?
Desirializer used - System.Text.Json;
Project asp .net core 3.1

The problem is that the properties you are looking for in the JSON array are actually wrapped inside an object called "tournament". It's easier to notice when you format the JSON string nicely like this for example:
[
{
"tournament": {
"id": 1,
"name": "name1",
...
}
},
{
"tournament": {
"id": 2,
"name": "name2",
...
}
}
]
To deserialize this I would suggest you make a wrapper class to handle that:
public class TournamentItem
{
[JsonPropertyName("tournament")]
public Tournament Tournament { get; set; }
}
And then deserialize to that class:
var data = await JsonSerializer.DeserializeAsync<IEnumerable<TournamentItem>>(responseStream);
Now data.Tournament will contain all the properties.
There might still be a few issues in your properties like Spam for example. The JSON string has a null as value, but the property is not nullable - I didn't check all your properties. DeserializeAsync will throw an error and tell you.

Related

Convert JSON response to Graph.EducationAssignment Object

When I attempt to convert a JSON response to a Graph.EducationAssignment root Object there is no data. I get no error message, just an empty object.
I'm calling /beta/education/classes/{classId}/assignments
HttpResponseMessage response = await HttpClient.GetAsync(webApiUrl);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
Microsoft.Graph.EducationAssignment Assignments =
JsonConvert.DeserializeObject<Microsoft.Graph.EducationAssignment>(json);
// List<Microsoft.Graph.EducationAssignment> Assignments1 =
// JsonConvert.DeserializeObject<List<Microsoft.Graph.EducationAssignment>>(json);
}
Due to the size of the response, here is the first line, which shows that the assignments are held in an array.
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#education/classes('id')/assignments",
"value": [
{
"classId": "blah-blah",
"displayName": "The homeless",
"closeDateTime": null
I'd appreciate it if somebody could help me out.
You don't describe what Microsoft.Graph.EducationAssignment looks like or where it came from. The most likely issue is that you're trying to deserialize a collection of resources (which is contained in value) into a single object.
Unless you're familiar with OData and JSON serialization, I'd avoid trying to hand-craft your own Graph client. You will have a much easier time using the Microsoft Graph Beta SDK. The SDK will handle all of this for you and you'll end up with cleaner code:
var assignments = await graphClient
.Education
.Classes["id"]
.Assignments
.Request()
.GetAsync();
var assignment = await graphClient
.Education
.Classes["id"]
.Assignments["id"]
.Request()
.GetAsync();

Unable to deserialize JSON in C# using the same class at both ends

I'm looking for someone to point out the obvious blunder here.
A .NET Core in C# application makes an HTTP call to another such application. Some processing is performed, and a response is sent thus:
Response response = new Response(input)
{
stuff = processedStuff;
};
responseMessage = JsonConvert.SerializeObject(response);
return new OkObjectResult(responseMessage);
This all looks good and responseMessage contains valid JSON (according to an online JSON checker I found).
At the other end, this is received thus:
Response returned = new Response();
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
returned = JsonConvert.DeserializeObject<Response>(json);
}
This fails with an Error converting value *the JSON string* to "Response" at line 1
Response is the same class file in both applications. What never obvious and apparently invisible mistake am I making here?
The invisible mistake you are making is double-serializing the result. The contract of OkObjectResult is that it will automatically serialize the result object to the negotiated content type (e.g. JSON or XML) and return an OK status. You are serializing the object first and then passing the serialized string to OkObjectResult so it ends up getting serialized twice.
responseMessage = JsonConvert.SerializeObject(response); // serialize to JSON
return new OkObjectResult(responseMessage); // implicit serialization here
Possible solutions:
Allow the implicit serialization to do its thing (recommended):
return new OkObjectResult(response); // implicit serialization of response object
Use a ContentResult instead (good if you need special serialization handling):
responseMessage = JsonConvert.SerializeObject(response); // serialize to JSON
return new ContentResult()
{
Content = responseMessage,
ContentType = "application/json",
StatusCode = 200
};
Deserialize twice on the receiving end (use as a last resort, i.e. you don't control the server):
var doubleSerializedJson = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<string>(doubleSerializedJson);
returned = JsonConvert.DeserializeObject<Response>(json);
check if the returned string is not wrapped in OkObjectResult object.
As far as I know, you don't need the serialization and deserialization, the framework already takes care of everything. If you need to, you could always deserialize to either an anonymous type or cast it from object.
https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm
I would also help if you could share the response class, since it's most likely part of the problem.
As someone old enough to remember when the Simpsons started, I can only answer in the traditional manner:
D'oh!
Using implicit serialization as described by the kind responder above resolved the issue.

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];

Parse JSON response where the object starts with a number in c#

I'm trying to deserialise a response from a REST service into C# Strongly typed classes - however I've ran into the same issue has in this post:
How do I output this JSON value where the key starts with a number?
However I have the issue that you cannot start a variable name in c# with a number - meaning that the class at that level just deserialises into null.
I need to know how to get into the objects and deserialise them into the c# classes.
My Current code is below:
public static async Task<T> MakeAPIGetRequest<T>(string uri)
{
Uri requestURI = new Uri(uri);
using (HttpClient client = new HttpClient())
{
HttpResponseMessage responseGet = await client.GetAsync(requestURI);
if (responseGet.StatusCode != HttpStatusCode.OK)
{
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
responseGet.StatusCode,
responseGet.Content));
}
else
{
string response = await responseGet.Content.ReadAsStringAsync();
T objects = (JsonConvert.DeserializeObject<T>(response));
return objects;
}
}
}
EDIT: I cannot change the way the service is pushing the data back
The correct way to deal with this was to use the JsonProperty tag on the target classes to define what Json property to listen for, as shown below (referenced from https://stackoverflow.com/questions/24218536/deserialize-json-that-has-some-property-name-starting-with-a-number
public class MyClass
{
[JsonProperty(PropertyName = "24hhigh")]
public string Highest { get; set; }
...
Thanks to #HebeleHododo for the comment answer
While there is no direct way to construct a strongly typed C# object in this case, You could still have the capabilities to parse the json string manually and extract values -
var json = "{'1':{'name':'test','age':'test'}}";
var t = JObject.Parse(json)["1"];
Console.WriteLine(t["name"]); //test
Console.WriteLine(t["age"]); //test

Read Json from response and convert it to Json Object [duplicate]

This question already has answers here:
How to output Json string as JsonResult in MVC4?
(2 answers)
Closed 6 years ago.
So I’m Calling a Web API From a ASP.NET core application. Im using HttpClient and reading it in as a string but i want to read it as a JSON object. I'm aware that that you can read it as Generic class ReadAsAsync<Generic>(); However, the returning object is a massive JSON object and it would be to much work to write a Generic class for it. My question is how can i just read it as its JSON object ?
public async Task<IActionResult> SendRequest()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(" https://api.forecast.io/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
HttpResponseMessage response = await client.GetAsync("forecast/KEY/");
if (response.IsSuccessStatusCode)
{
var forcast = await response.Content.ReadAsStringAsync();
Console.WriteLine("{0}", forcast);
// return Json( JSON ) ;
}
}
// return Json( JSON ) ;
}
I see Three types of response readers, can any of these become JSON objects ?
ReadAsByteArrayAsync, ReadAsStreamAsync, ReadAsStringAsync
Use Json.NET to convert the string to an object (and viceversa):
http://www.newtonsoft.com/json/help/html/Overload_Newtonsoft_Json_JsonConvert_DeserializeObject.htm
You can try parsing your JSON payload as JObject which would essentially allow you to even use LINQ to JSON.
Sample code from here:
JObject o = JObject.Parse(#"{
'CPU': 'Intel',
'Drives': [
'DVD read/writer',
'500 gigabyte hard drive'
]
}");
string cpu = (string)o["CPU"];
// Intel
string firstDrive = (string)o["Drives"][0];
// DVD read/writer
IList<string> allDrives = o["Drives"].Select(t => (string)t).ToList();
// DVD read/writer
// 500 gigabyte hard drive
Technically this would be much more appropriate for your case where you dont want a POCO to represent your payload.
And Json.net 4.0+ would actually allow you to use a dynamic instance too:
dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
jsonResponse.Works = true;
Console.WriteLine(jsonResponse.message); // Hi
Console.WriteLine(jsonResponse.Works); // True
Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
Assert.That(jsonResponse, Is.TypeOf<JObject>());
See more on this here

Categories

Resources