Azure Deserialize JSON Response C# - c#

I try to deserialize my JSON Response which is at below, but when i print the content of each parameter, it shows error.
My JSON Resposne:
[
{
"faceRectangle": {
"top": 214,
"left": 472,
"width": 450,
"height": 450
},
"faceAttributes": {
"age": 19.0,
"emotion": {
"anger": 0.0,
"contempt": 0.0,
"disgust": 0.0,
"fear": 0.0,
"happiness": 0.0,
"neutral": 0.996,
"sadness": 0.003,
"surprise": 0.001
}
}
}
]
I able to deserialize my code with this:
public static async Task<List<RootObject>> MakeAnalysisRequest(string imageFilePath)
{
HttpClient client = new HttpClient();
// Request headers.
client.DefaultRequestHeaders.Add(
"Ocp-Apim-Subscription-Key", subscriptionKey);
// Request parameters. A third optional parameter is "details".
string requestParameters = "&returnFaceId=false&returnFaceLandmarks=false&returnFaceAttributes=age,emotion";
// Assemble the URI for the REST API Call.
string uri = uriBase + "?" + requestParameters;
HttpResponseMessage response;
// Request body. Posts a locally stored JPEG image.
byte[] byteData = GetImageAsByteArray(imageFilePath);
using (ByteArrayContent content = new ByteArrayContent(byteData))
{
// This example uses content type "application/octet-stream".
// The other content types you can use are "application/json"
// and "multipart/form-data".
content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
// Execute the REST API call.
response = await client.PostAsync(uri, content);
// Get the JSON response.
string contentString = await response.Content.ReadAsStringAsync();
// Display the JSON response.
Console.WriteLine("\nResponse:\n");
string format = JsonPrettyPrint(contentString);
var deserializedJson = JsonConvert.DeserializeObject<List<RootObject>>(format);
Console.WriteLine(format);
Console.WriteLine(deserializedJson);
Console.WriteLine("\nPress Enter to exit...");
return deserializedJson;
}
}
But when i try to print each parameter value, it shows error:
var output1 = MakeAnalysisRequest(imageFilePath).Result;
var x= output1[0].FaceAttributes.Emotion.Anger;
Console.WriteLine(x);
var y = output1[1].FaceAttributes.Emotion.Neutral;
Console.WriteLine(y);
if (x >= 0.5)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"D:\Degree course outline\FYP2019\soft.wav");
player.Play();
}
if (y>= 0.5)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"D:\Degree course outline\FYP2019\soft.wav");
player.Play();
}
My error code is like this:
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
How could i solve it?
Thanks
My class object:
class Program
{
public class FaceRectangle
{
public int Top { get; set; }
public int Left { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
public class Emotion
{
public double Anger { get; set; }
public double Contempt { get; set; }
public double Disgust { get; set; }
public double Fear { get; set; }
public double Happiness { get; set; }
public double Neutral { get; set; }
public double Sadness { get; set; }
public double Surprise { get; set; }
}
public class FaceAttributes
{
public double Age { get; set; }
public Emotion Emotion { get; set; }
}
public class RootObject
{
public FaceRectangle FaceRectangle { get; set; }
public FaceAttributes FaceAttributes { get; set; }
}

Try this code:
var output1 = await MakeAnalysisRequest(imageFilePath);
if (output1 != null && output1.Count > 0)
{
var x= output1[0].FaceAttributes.Emotion.Anger;
Console.WriteLine(x);
}
if (output1 != null && output1.Count > 1)
{
var y = output1[1].FaceAttributes.Emotion.Neutral;
}
The out of range exception is there because your deserialized output does not have enough elements to access. Please share your class object for more help.
Also try to avoid using the .Result to get the return value from asynch as it could lead to deadlocks.
Edit after providing class
With your class being like this then change your code accordingly:
var output1 = await MakeAnalysisRequest(imageFilePath);
if (output1 != null && output1.Count > 0)
{
var x= output1[0].FaceAttributes.Emotion.Anger;
Console.WriteLine(x);
var y = output1[0].FaceAttributes.Emotion.Neutral;
Console.WriteLine(y);
}
There is only one RootObject in your jsons array that is comprised of two others.
Json array [] object {}
An array with two objects looks like this [{},{}] and not like this [{{},{}}]

Related

Post With C# WebClient Multiple Json Object

I want to send Post Request with C# WebClient with this Json Schema :
[
{
"id": "00000000-0000-0000-0000-000000000000",
"points": [
{
"timestamp": "2017-12-04T16:07:44.562Z",
"value": 0
}
]
}
]
I've tried This :
public class RequestData
{
public string id {get; set; }
public points points { get; set; }
}
public class points
{
public DateTime timestamp { get; set; }
public float value { get; set; }
}
My Program :
Random number = new Random();
var req = new RequestData();
req.id = "0e13d9c-571c-44f4-b796-7c40c0e20a1d";
req.points = new points { timestamp = DateTime.UtcNow, value =
number.Next(100, 99999) };
JsonSerializerSettings settings = new JsonSerializerSettings();
var data = JsonConvert.SerializeObject(req);
WebClient client = new WebClient();
client.Headers.Add(HttpRequestHeader.Authorization,
AquaAtuhorization.accessToken);
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
client.UploadString ("http://localhost:8080/api/v1/data/writeNumericValues",
data );
And I always get Http 415 (Unsupported Media Type).
How could I format my C# Object as the restApi accepeted Format.
Look at the JSON, the square brackets [ ] denote that something is an array. In this case both RequestData and points have to be an array, see the example below:
public class RequestData
{
public string id { get; set; }
public List<points> points { get; set; } // I use list, could be an array
}
public class points
{
public DateTime timestamp { get; set; }
public float value { get; set; }
}
Then construct your req object like this:
var req = new List<RequestData> // Again I use list, could be an array
{
new RequestData
{
id = "0e740d9c-571c-44f4-b796-7c40c0e20a1d",
points = new List<points> // Defined as a list, even though it has one entry
{
new points
{
timestamp = DateTime.UtcNow,
value = number.Next(100, 99999)
}
}
}
};
Then just serialize it as normal, the result will be the below:
[
{
"id":"0e740d9c-571c-44f4-b796-7c40c0e20a1d",
"points":[
{
"timestamp":"2017-12-04T17:12:25.8957648Z",
"value":59522.0
}
]
}
]
Your Json class needs to be like this, see http://json2csharp.com/ or use paste as JSON from VS https://blog.codeinside.eu/2014/09/08/Visual-Studio-2013-Paste-Special-JSON-And-Xml/
public class Point
{
public DateTime timestamp { get; set; }
public int value { get; set; }
}
public class RootObject
{
public string id { get; set; }
public List<Point> points { get; set; }
}`

StatusCode: 401, ReasonPhrase: 'Unauthorized' gets displayed when calling a Post Method through HTTPClient using C#

I am trying to access an API's Post method through HTTP Client and passing the AuthToken. When I tried to access in post man I am able to get the response, but when I ran in C#, I got StatusCode: 401, ReasonPhrase: 'Unauthorized' error. I am sharing the request and Response screens of Postman along with my code. can anyone let me know the mistake which i did in the code and how to solve the issue.
Postman Request Header and Response Body
Postman Request Body
below is my C# code.
public class PostEmpData
{
public string cExternalGUID = "10134",
cEmployeeID = "10134", cLastName = "Anderson", cFirstName = "Derek", cAccessGroup = "", cActive = "A";
public int nCardNumber = 10134, nPayMethod = 2;
public string[] cGroupsList = new string[0] { };
public DateTime dHireDate = DateTime.Parse("1999 / 11 / 03"), dTermDate = DateTime.Parse("01 / 01 / 0001"), dRateEffectiveDate = DateTime.Parse("2017 - 07 - 15");
public decimal nPayRate = 1500;
}
public class PostEmployeeClass
{
public int _interfaceID { get; set; }
public int _errorCode { get; set; }
public string _errorDescription { get; set; }
public List<EmpPostResponse> respList;
}
public class EmpPostResponse
{
public string RetKey { get; set; }
public int ErrorCode { get; set; }
public string Description { get; set; }
public string Success { get; set; }
public string SecondaryList { get; set; }
}
static async Task<List<EmpPostResponse>> CallPostEmployeeAsync(object postdata)
{
Console.WriteLine("Post Employee Process Started");
PostEmployeeClass authclass = null;
List<EmpPostResponse> data = null;
HttpResponseMessage response = await client.PostAsJsonAsync("xxxxxxV2/api/ED907F98-9132-4C7D-B4D4-7648A2577F6D/Integration/employees", postdata);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
Console.WriteLine("success");
authclass = await response.Content.ReadAsAsync<PostEmployeeClass>();
data = authclass.respList;
}
else
Console.WriteLine("fail:" + response.StatusCode.ToString());
return data;
}
static void Main(string[] args)
{
Console.WriteLine("Starting the Process");
RunAsync().Wait();
}
static async Task RunAsync()
{
PostEmpData objPost = new PostEmpData();
client.BaseAddress = new Uri("https://xxxx.xxxxx.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
string AuthToken="XXXXXXXXXXXXX";
client.DefaultRequestHeaders.Add("AuthToken", AuthToken);
Console.WriteLine(AuthToken);
var postdata = CallPostEmployeeAsync(objPost);
}catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
I've reviewed your code and there are a few things that I noticed.
One thing that is not going to work: PostEmpData will serialize into an empty object as it contains no properties. So the body will be something like: {}. You will need to add properties to the class:
public class PostEmpData
{
public string cExternalGUID { get; set; } = "10134";
public string cEmployeeID { get; set; } = "10134";
public string cLastName { get; set; } = "Anderson";
public string cFirstName { get; set; } = "Derek";
public string cAccessGroup { get; set; } = "";
public string cActive { get; set; } = "A";
public int nCardNumber { get; set; } = 10134;
public int nPayMethod { get; set; } = 2;
public string[] cGroupsList { get; set; }= new string[0] { };
public DateTime dHireDate { get; set; }= DateTime.Parse("1999 / 11 / 03");
public DateTime dTermDate { get; set; }= DateTime.Parse("01 / 01 / 0001");
public DateTime dRateEffectiveDate { get; set; }= DateTime.Parse("2017 - 07 - 15");
public decimal nPayRate { get; set; }= 1500;
}
There is a good chance that this causes the unauthorized response. And that it may have nothing to do with the token.
And there is also another difference compared to the Postman request. With Postman you send an array of object [{}], but with code you send one object. So you may have to post a list of PostEmpData.

C# loading grid with json

I'm trying to load a grid with json that I receive. This is my code in Home.cs:
private void getTickets()
{
try
{
string urlName = "tickets";
string method = "GET";
string json = null;
HttpStatusCode statusCode = HttpStatusCode.Forbidden;
Tickets data = null;
RestClient client = RequestClient.makeClient();
MakeRequest request = new MakeRequest(null, null, urlName, method);
IRestResponse response = client.Execute(request.exec());
statusCode = response.StatusCode;
json = response.Content;
var ticketWrapper = JsonConvert.DeserializeObject<TicketWrapper>(json);
if ((int)statusCode == 200)
{
gridTicket.DataSource = ticketWrapper.tickets;
}
else
{
MessageBox.Show("error");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Ticket wrapper class
class TicketWrapper
{
public IEnumerable<Tickets> tickets { get; set; }
}
Tickets class
class Tickets
{
public int id;
public string title;
public string description;
public int user_id;
public int subject_id;
}
If I debug I can see that I receive the json but ticketWrapper is null what could be wrong here?
Debug image:
Try to change public fields in Ticket class to properties:
class Tickets
{
public int id { get; set; }
public string title { get; set; }
public string description { get; set; }
public int user_id { get; set; }
public int subject_id { get; set; }
}
Also I think that IEnumerable is not the best option for serialization. Try to use List in TicketWrapper.
Additionally move your break point down, because in current position ticketWrapper will be always null (expression has not yet been executed).

Displaying Project Oxford's Emotion API result in C#

I have trouble displaying the result returned by Emotion API. Result is returned in form of Emotion[]. The code is as follows
private async void button2_Click(object sender, EventArgs e)
{
try
{
pictureBox2.Image = (Bitmap)pictureBox1.Image.Clone();
String s = System.Windows.Forms.Application.StartupPath + "\\" + "emotion.jpg";
pictureBox2.Image.Save(s);
string imageFilePath = s;// System.Windows.Forms.Application.StartupPath + "\\" + "testing.jpg";
Uri fileUri = new Uri(imageFilePath);
BitmapImage bitmapSource = new BitmapImage();
bitmapSource.BeginInit();
bitmapSource.CacheOption = BitmapCacheOption.None;
bitmapSource.UriSource = fileUri;
bitmapSource.EndInit();
// _emotionDetectionUserControl.ImageUri = fileUri;
// _emotionDetectionUserControl.Image = bitmapSource;
System.Windows.MessageBox.Show("Detecting...");
***Emotion[] emotionResult*** = await UploadAndDetectEmotions(imageFilePath);
System.Windows.MessageBox.Show("Detection Done");
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
}
and I need to find the most dominant emotion from results of various emotions.
I went to the API reference. It returns JSON like this:
[
{
"faceRectangle": {
"left": 68,
"top": 97,
"width": 64,
"height": 97
},
"scores": {
"anger": 0.00300731952,
"contempt": 5.14648448E-08,
"disgust": 9.180124E-06,
"fear": 0.0001912825,
"happiness": 0.9875571,
"neutral": 0.0009861537,
"sadness": 1.889955E-05,
"surprise": 0.008229999
}
}
]
I pasted that into http://json2csharp.com/ and it generated some classes for me. (I renamed the root class to Emotion and replaced the scores class with an IDictionary<string, double>. That's because you don't just want a property for each emotion. You want a set that you can sort to find the highest emotion. (IDictionary<string, double> was what most easy to deserialize the json into.)
public class FaceRectangle
{
public int left { get; set; }
public int top { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Emotion
{
public FaceRectangle faceRectangle { get; set; }
public IDictionary<string, double> scores { get; set; }
}
Then I wrote a unit test and pasted in the JSON from Microsoft's API page to see if I could deserialize it. I added the Newtsonsoft.Json Nuget package and wrote this:
[TestClass]
public class DeserializeEmotion
{
[TestMethod]
public void DeserializeEmotions()
{
var emotions = JsonConvert.DeserializeObject<Emotion[]>(JSON);
var scores = emotions[0].scores;
var highestScore = scores.Values.OrderByDescending(score => score).First();
//probably a more elegant way to do this.
var highestEmotion = scores.Keys.First(key => scores[key] == highestScore);
Assert.AreEqual("happiness", highestEmotion);
}
private const string JSON =
"[{'faceRectangle': {'left': 68,'top': 97,'width': 64,'height': 97},'scores': {'anger': 0.00300731952,'contempt': 5.14648448E-08,'disgust': 9.180124E-06,'fear': 0.0001912825,'happiness': 0.9875571,'neutral': 0.0009861537,'sadness': 1.889955E-05,'surprise': 0.008229999}}]";
}
The test passes, so that's it. You've got a Dictionary<string,double> containing the scores, so you can both display them and find the emotion with the highest score.

How do I deserialize my JSON?

What would be my next step to take? I want to be able to write the block with the id value of ex 1. Or the block with ex GPIO value 3 with something simple as maybe WriteLine(id1) Relay.cs
public class Relay
{
public int GPIO { get; set; }
public int id { get; set; }
public int status { get; set; }
public string type { get; set; }
}
Program.cs
static void Main(string[] args)
{
var client = new RestClient("http://192.168.0.3:1337/auto/api/v1.0/");
var request = new RestRequest("relays", Method.GET);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var response = client.Execute<Relay>(request);
Console.WriteLine(response.Content);
Console.ReadLine();
}
and my array on 192.168.0.3:1337/auto/api/v1.0/relays
{
"relays": [
{
"GPIO": 2,
"id": 1,
"status": 0,
"type": "Relay"
},
{
"GPIO": 3,
"id": 2,
"status": 0,
"type": "Relay"
}
]
}
I'm sorry if anything is unclear, or if the answer is simple. If I missed to include something important, just point it out and I'll post it!
you can deserialize it in List of Relay and iterate and read any value you want
static void Main(string[] args)
{
var client = new RestClient("http://192.168.0.3:1337/auto/api/v1.0/");
var request = new RestRequest("relays", Method.GET);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var response = client.Execute<Relay>(request);
JavaScriptSerializer ser = new JavaScriptSerializer();
var relayList = ser.Deserialize<List<Relay>>(response.Content);
foreach(Relay relay in relayList)
Console.WriteLine(relay.ID);
Console.ReadLine();
}
You need to parse that JSON into objects to manipulate them, and it seems that your REST client already does it, just need to pass the correct type.
1-Create the class structure like the structure you're receiving:
public class Relay
{
public int GPIO { get; set; }
public int id { get; set; }
public int status { get; set; }
public string type { get; set; }
}
public class RelayCollection
{
public Relay[] relays { get; set; }
}
2-Parse the received json:
var relayCollection = client.Execute<RelayCollection>(request);
Now you have all the relays inside relayCollection.relays, manipulate them as any other array/class
Beforehand I apologize for my English, but you can serialize a json by creating a list of your class and then deserialize the json like this:
public class Relay {
int GPIO;
public int gPIO {get {return GPIO;} set {GPIO=value;}}
int Id;
public int ID {get {return Id;} set {Id = value;}}
int Status;
public int status {get {return Status;} set {Status = value;}}
string Type;
public string type {get {return Type;} set {Type = value;}}
}
Now create a class list
List<Relay > relayList = new List<Relay >();
And finally deserealize the json
relayList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Relay>>(request);

Categories

Resources