I try to get the first image from wikipedia api. I wrote the following C# code to retrieve the source from Thumbnail. But whenever I run the code it shows exception
An unhandled exception of type 'Newtonsoft.Json.JsonReaderException'
occurred in Newtonsoft.Json.dll Additional information: Unexpected
character encountered while parsing value: <. Path '', line 0,
position 0.
My code is as follows
public class Thumbnail
{
public string source { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class Pageval
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public Thumbnail thumbnail { get; set; }
public string pageimage { get; set; }
}
public class Query
{
public Dictionary<string, Pageval> pages { get; set; }
}
public class RootObject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
}
class Class1
{
public static PictureBox Image1 = new PictureBox();
public static Label Image1_title = new Label();
public static void Load_Image(string name1, string LocationName)
{
var startPath = Application.StartupPath;
string Imagefolder = Path.Combine(startPath, "Image");
string subImageFolder = Path.Combine(Imagefolder, LocationName);
System.IO.Directory.CreateDirectory(subImageFolder);
using (var wc = new System.Net.WebClient())
{
var uri = ("https://en.wikipedia.org/w/api.php?action=query&prop=pageimages&pithumbsize=400&titles="+name1);
var response = wc.DownloadString(new Uri(uri));
var responseJson = JsonConvert.DeserializeObject<RootObject>(response);
var firstKey = responseJson.query.pages.First().Key;
string image1 = responseJson.query.pages[firstKey].thumbnail.source;
string Image_title = responseJson.query.pages[firstKey].title;
Image1.SizeMode = PictureBoxSizeMode.StretchImage;
Image1.LoadAsync(image1);
Image1_title.Text = Image_title;
}
}
}
}
In form1.cs I call this class in the follwing way. and in Textbox I wrote the name such as Berlin.
private void button1_Click(object sender, EventArgs e)
{
Class1.Image1 = pictureBox1;
Class1.Load_Image(textBox1.Text, textBox1.Text);
}
I am not finding out what is the problem with this code
The json I got is
{
"batchcomplete": "",
"query": {
"pages": {
"3354": {
"pageid": 3354,
"ns": 0,
"title": "Berlin",
"thumbnail": {
"source": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Siegessaeule_Aussicht_10-13_img4_Tiergarten.jpg/400px-Siegessaeule_Aussicht_10-13_img4_Tiergarten.jpg",
"width": 400,
"height": 267
},
"pageimage": "Siegessaeule_Aussicht_10-13_img4_Tiergarten.jpg"
}
}
}
}
If you look at the output of your query, it says this:
This is the HTML representation of the JSON format. HTML is good for debugging, but is unsuitable for application use.
Specify the format parameter to change the output format. To see the non-HTML representation of the JSON format, set format=json.
If you follow that advice, it should fix your error.
To display image from URL you need to use WebClient to load image in local system.
ie.
string remoteUri = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Siegessaeule_Aussicht_10-13_img4_Tiergarten.jpg/400px-Siegessaeule_Aussicht_10-13_img4_Tiergarten.jpg";
string fileName = "MyImage.jpg",
WebClient myWebClient = new WebClient();
myWebClient.DownloadFile(remoteUri,fileName);
Related
I would like to start by saying that I am not a developer and this is my very first time writing a code to this extend of complication (at least to me). Any help/guidance would be much appreciated.
The idea of this program is to retrieve the employee user ID (or signature) from an API URL once the name has been entered.
I created a class that identifies the information that needs to be retrieved from the API (Below is the code):
namespace TimeSheet_Try11_Models
{
public class Employeename
{
public List<string> Signature { get; set; }
public List<string> FirstName { get; set; }
public List<string> FullName { get; set; }
public List<string> LastName { get; set; }
}
}
Next I created a folder called WebAPI which will access the API and retrieve the needed information. (please see the code)
namespace TimeSheets_Try_11.Controllers
{
class WebAPI
{
public string Getsignature(string name)
{
var cookies = FullWebBrowserCookie.GetCookieInternal(new Uri(StaticStrings.UrlIora), false);
WebClient wc = new WebClient();
wc.Encoding = System.Text.Encoding.UTF8;
wc.Headers.Add("Cookie:" + cookies);
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
wc.UseDefaultCredentials = true;
string uri = "";
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
uri = StaticStrings.UrlIora + name;
var response = wc.DownloadString(uri);
string json = #"[{'signature':'JANDO','firstName':'Jane','fullName':'Deo, Jane','lastName':'Deo'}]";
Employeename status = JsonConvert.DeserializeObject<Employeename>(json);
string signature = status.Signature.ToString();
return signature;
}
}
}
Finally, the following code is my code for the forms that will retrieve and display information.
namespace TimeSheets_Try_11
{
public partial class Form1 : Form
{
WebAPI WA = new WebAPI();
public Form1()
{
InitializeComponent();
webBrowser1.Url = new Uri(StaticStrings.UrlIora);
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
string strurltest = string.Format("https://iora.UniversityofHouston.com/api/dictionary/employee/" + textBox1.Text);
System.Net.WebRequest requestObjGet = WebRequest.Create(strurltest);
requestObjGet.Credentials = CredentialCache.DefaultNetworkCredentials;
requestObjGet.Method = "Get";
HttpWebResponse reponsObjGet = null;
reponsObjGet = (HttpWebResponse)requestObjGet.GetResponse();
string[] usernames = new string[] { "Koehne, Craig", "Bergeron, Ronald" };
string[] userid = new string[] { "CKOEH", "RONBE" };
for (int i = 0; i < usernames.Length; i++)
{
if (textBox1.Text.Contains(usernames[i]))
{
textBox2.Text = userid[i];
}
}
string sgname; string projectstring;
projectstring = textBox1.Text.ToString();
sgname = WA.Getsignature(projectstring);
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
string StringConn = textBox1.Text;
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
}
}
}
Problem: The code does not seem to have any errors, however when I start debugging the code, it gives me an error that states:
"Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'TimeSheet_Try11_Models.Employeename' because the type requires a JSON
object (e.g. {"name":"value"}) to deserialize correctly."
Your JSON string contains an array that contains one object. But you're trying to deserialize it into just a single object.
Either deserialize the JSON string into a C# array:
string json = #"[{'signature':'JANDO','firstName':'Jane','fullName':'Deo, Jane','lastName':'Deo'}]";
Employeename[] status = JsonConvert.DeserializeObject<Employeename[]>(json);
Or change the JSON string so it's no longer an array, just an object:
string json = #"{'signature':'JANDO','firstName':'Jane','fullName':'Deo, Jane','lastName':'Deo'}";
Employeename status = JsonConvert.DeserializeObject<Employeename>(json);
Also, your Employeename class makes no sense, the properties should be of type string:
public class Employeename
{
public string Signature { get; set; }
public string FirstName { get; set; }
public string FullName { get; set; }
public string LastName { get; set; }
}
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 [{{},{}}]
I am trying to talk to an api (isbndb.com) and i can succesfully get a response. Using a streamreader i can even get a string containing json. However that string will also contain special characters for linebreaks etc.
Therefore i cant deserialize the json. The string content looks like this :
"{\n \"book\":\n \n {\n \"publisher\":\"Pearson\",\n \"language\":\"Eng\",\n \"image\":\"https:\\/\\/images.isbndb.com\\/covers\\/34\\/13\\/9780134093413.jpg\",\n \"title_long\":\"Campbell Biology (11th Edition)\",\n \"edition\":\"11\",\n \"pages\":1488,\n \"date_published\":\"2017\",\n \"subjects\":[\"Biology\"],\n \"authors\":[\"Lisa A. Urry\",\"Michael L. Cain\",\"Steven A. Wasserman\",\"Peter V. Minorsky\",\"Jane B. Reece\"],\n \"title\":\"Campbell Biology (11th Edition)\",\n \"isbn13\":\"9780134093413\",\n \"msrp\":\"259.99\",\n \"binding\":\"Hardcover\",\n \"publish_date\":\"2017\",\n \n \n \"isbn\":\"0134093410\"\n }\n }"
The method that gets me this result looks like this :
public bool TryGetBook(string isbn)
{
bool rtnValue = false;
string WEBSERVICE_URL = Globals.WEBSERVICE_URL + isbn;
try
{
var webRequest = WebRequest.Create(WEBSERVICE_URL);
if (webRequest != null)
{
webRequest.Method = "GET";
webRequest.ContentType = "application/json";
webRequest.Headers["Authorization"] = Globals.REST_KEY;
//Get the response
WebResponse wr = webRequest.GetResponseAsync().Result;
Stream receiveStream = wr.GetResponseStream();
StreamReader reader = new StreamReader(receiveStream);
string content = reader.ReadToEnd();
if (content != null)
{
Book book = JsonConvert.DeserializeObject<Book>(content);
if (book != null)
{
Books.Add(book);
rtnValue = true;
}
}
}
}
catch (Exception ex)
{
}
return rtnValue;
}
I am not really sure what to do here, i could write a regex expression to clean up my sample data but that just seems like the wrong way to go about it.
any help is much appreciated.
You can replace all line breaks by using the following snippet
string content = json.Replace("\n", "");
Environment.NewLine doesn't work here. There is a formatted content below
{
"book":
{
"publisher": "Pearson",
"language": "Eng",
"image": "https:\/\/images.isbndb.com\/covers\/34\/13\/9780134093413.jpg",
"title_long": "Campbell Biology (11th Edition)",
"edition": "11",
"pages": 1488,
"date_published": "2017",
"subjects": ["Biology"],
"authors": ["Lisa A. Urry", "Michael L. Cain", "Steven A. Wasserman", "Peter V. Minorsky", "Jane B. Reece"],
"title": "Campbell Biology (11th Edition)",
"isbn13": "9780134093413",
"msrp": "259.99",
"binding": "Hardcover",
"publish_date": "2017",
"isbn": "0134093410"
}
}
Then copy the updated string and use Edit-Paste Special-Paste JSON as classes. There is generated classes
public class BookResponse
{
public Book book { get; set; }
}
public class Book
{
public string publisher { get; set; }
public string language { get; set; }
public string image { get; set; }
public string title_long { get; set; }
public string edition { get; set; }
public int pages { get; set; }
public string date_published { get; set; }
public string[] subjects { get; set; }
public string[] authors { get; set; }
public string title { get; set; }
public string isbn13 { get; set; }
public string msrp { get; set; }
public string binding { get; set; }
public string publish_date { get; set; }
public string isbn { get; set; }
}
Actually, the Book instance is nested in a different class. So, for parsing you have to use something like that
var response = JsonConvert.DeserializeObject<BookResponse>(content);
if (response.book != null)
{
}
You can try first replacing your line breaks by empty strings.
content = content.Replace("\\n",""); and then deserialize. Good luck.
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; }
}`
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.