As in the topic, I'm making a request to an endpoint, which in return gives me a json string. Sample json string (picked up 6 substrings, there is about thousand more):
{"probability":0.0062596053,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.27482307,"top":0.4361664,"width":0.14311266,"height":0.37521422}},
{"probability":0.0061301645,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.0,"top":0.44423538,"width":0.09239961,"height":0.37426883}},
{"probability":0.0059485333,"tagId":"sometagid","tagName":"carrot","boundingBox":{"left":0.037714787,"top":0.0,"width":0.15685204,"height":0.27176687}},
{"probability":0.005887271,"tagId":"sometagid","tagName":"tomato","boundingBox":{"left":0.5249929,"top":0.70379305,"width":0.44499594,"height":0.29620594}},
{"probability":0.0057223,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.79498,"top":0.34279144,"width":0.19351125,"height":0.39170527}},
{"probability":0.0056102676,"tagId":"sometagid","tagName":"apple","boundingBox":{"left":0.030394234,"top":0.21933028,"width":0.16375154,"height":0.3037323}},
What do I need? I need this string to be splitted into these 6 (+1000) objects (preferably to an array) and I want to pick only these object that contain probability*100 > 50.
I've already made a class that contains such values as:
public class ResponseJsonNode {
public double probability { get; set; }
public string tagId { get; set; }
public string tagName { get; set; }
public BoundingBox boundingBox { get; set; }
}
And BoundingBox is another class:
public class BoundingBox {
double left { get; set; }
double top { get; set; }
double width { get; set; }
double height { get; set; }
}
Reproducible example (well not quite really because i can't post endpoint and key here):
using System.Net;
using System.Text.Json;
using ConsoleApp1;
WebRequest request = HttpWebRequest.Create("SomeUriEndpoint");
request.Method = "POST";
request.Headers.Add("some key", "some more key");
request.Headers.Add("some content type", "some more content type");
var f = File.Open(args[0], FileMode.Open);
using (var ms = new MemoryStream()) {
f.CopyTo(ms);
var fileBytes = ms.ToArray();
request.ContentLength = fileBytes.Length;
Stream stream = request.GetRequestStream();
stream.Write(fileBytes, 0, fileBytes.Length);
stream.Close();
//imageStringBase64 = Convert.ToBase64String(fileBytes);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result;
string json = new StreamReader(response.GetResponseStream()).ReadToEnd();
//JsonObject jo = (JsonObject)json;
List<ResponseJsonNode> jsonNodeList = JsonSerializer.Deserialize<List<ResponseJsonNode>>(json);
foreach(ResponseJsonNode rj in jsonNodeList) {
Console.WriteLine(rj);
}
And this gives me an error:
The JSON value could not be converted to System.Collections.Generic.List
This does not work also:
HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result;
string json = new StreamReader(response.GetResponseStream()).ReadToEnd();
//JsonObject jo = (JsonObject)json;
//List<ResponseJsonNode> jsonNodeList = JsonSerializer.Deserialize<List<ResponseJsonNode>>(json);
JsonArray jsonArray = JsonNode.Parse(json).AsArray();
List<ResponseJsonNode> nodes = new List<ResponseJsonNode>();
foreach(JsonObject jo in jsonArray) {
nodes.Add(new ResponseJsonNode { probability = Convert.ToDouble(jo["probability"]), tagName = (string)jo["tagName"] });
}
var stats = new Dictionary<string, double>();
foreach (ResponseJsonNode rjn in nodes) {
if (rjn.probability * 100 > 50)
if (stats.ContainsKey(rjn.tagName)) {
stats[rjn.tagName]++;
} else {
stats[rjn.tagName] = 1;
}
}
Throws an error: System.InvalidOperationException: The node must be of type 'JsonArray'
I have tried to parse it with numerous tutorials but every one of them seems deprecated or does not work (example shown above). So what is the best possible solution for converting json string into a iterable JsonObject? (Not specificly JsonObject class that is in c# libraries but something that i could iterate on)
[Updated from clarification in this comment above.]
The JSON you're showing isn't an array. Which is why you can't deserialize it into an array. It's an object which contains an array. But in order to access that array you need to deserialize the object.
So deserialize the object. For example, using this class:
public class ResponseObject
{
public IEnumerable<ResponseJsonNode> predictions { get; set; }
}
You can deserialize your object into that class:
ResponseJsonNode jsonNode = JsonSerializer.Deserialize<ResponseObject>(json);
Basically the problem you're running into is understanding the difference between an object and an array of objects, or an object and a property on an object. You need to understand your data structure(s) in order to use that data.
If your json is literally you shown, you need to modify it a little bit, then deserialize in a standard way.
public class ResponseJsonNode {
public double Probability { get; set; }
public string TagId { get; set; }
public string TagName { get; set; }
public BoundingBox BoundingBox { get; set; }
public override string ToString() =>
$"[Node]: Probability: {Probability}; TagId: {TagId}; TagName: {TagName};\nBoundingBox: {BoundingBox}";
}
public class BoundingBox
{
public double Left { get; set; }
public double Top { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public override string ToString() => $"[L:{Left};T:{Top};Width:{Width};Height:{Height}]";
}
Deserialize then:
var json = GetJsonFromApi();
var trimmedJson = $"[{json.TrimEnd(',')}]";
var collection = JsonSerializer.Deserialize<List<ResponseJsonNode>>(trimmedJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var item in collection)
{
Console.WriteLine($"{item}\n");
}
Btw, C# naming convention recommends name properties in a PascalCase, for deserialization from camelCase just use JsonSerializerDefaults.Web options.
and I want to pick only these object that contain probability*100 > 50.
Then simple LINQ filtration comes to the scene.
I have a wordpress.org locally hosted on my pc.
I've installed a wordpress plugin called json-api which let you retrieve posts from your wordpress site.
I'm running the following code:
var client = new RestClient(BlogArticlesUrl);
var request = new RestRequest();
request.Timeout = 5000;
request.RequestFormat = DataFormat.Json;
request.Method = Method.GET;
request.AddParameter("json", "get_tag_posts");
request.AddParameter("slug", "featured");
request.AddParameter("count", "3");
var articles = client.Execute<List<BlogArticleModel>>(request);
After executing the code, in the variable articles I have the following:
Inside the Content there are few keys but I would only like to convert 'posts' to a model in c#
How do I acheive that?
EDIT:
I have found a solution using newtonsoft for dot net
Newtonsoft.Json.JsonConvert.DeserializeObject<BlogArticleResponse>(articles.Content);
In RestSharp, the Content is what gets deserialized. So, the type you pass into the .Execute<T> method must be the same structure as the response.
In your case, it will look something like this:
public class BlogArticleResponse
{
public string status { get; set; }
public int count { get; set; }
public int pages { get; set; }
public BlogTag tag { get; set; }
...
}
public class BlogTag
{
public int id { get; set; }
public string slug { get; set; }
public string title { get; set; }
public string description { get; set; }
...
}
You can then execute the request like this:
var result = client.Execute<BlogArticleResponse>(request);
For more information, have a look at the documentation.
I am working on a wpf application. In this application I received JSON response from server and deserialize it as follow :-
StreamReader streamReader = new StreamReader(jsonResponse.GetResponseStream());
String responseData = streamReader.ReadToEnd();
var myData = JsonConvert.DeserializeObject<List<RootObject>>(responseData);
//UserData ud = new UserData();
foreach (var val in myData)
{
string res = val.response;
if (res == "true")
{
this.Hide();
new lobby().Show();
}
}
My class is as follow :-
public class RootObject
{
public string response { get; set; }
public string user_id { get; set; }
public string username { get; set; }
public string current_balance { get; set; }
public string message { get; set; }
public string oauth_token { get; set; }
public List<string> lastFiveSpinNumbers { get; set; }
}
When I execute this code everything is ok and after checking response lobby.xaml open. Now I need to access values of RootObject class in lobby.xaml.cs. So I created an instance of this class as follow:-
RootObject cd = new RootObject();
UserNameTextBlock.Text = cd.response;
but cd.response is always null. What may be the reason?
You are creating a new instance of RootObject and by default the response property is null.
You can give your lobby class a constructor that takes in a RootObject:
public class lobby
{
public lobby(RootObject rootObject)
{
UserNameTextBlock.Text = rootObject.response;
}
}
Then in your foreach you could do:
if (res == "true")
{
this.Hide();
new lobby(val).Show(); // Pass the root object to the Lobby constructor
}
Note: You may wish to rename lobby to Lobby for your class name, this adheres to better C# naming conventions.
I am using RESTSharp to receive and deserialize result from an API call. Response is JSON. I've created a class for the repsonse that looks like this:
public class JsonResponseClass
{
public class Selector
{
public static string verb { get; set; }
}
public class Points
{
public int definition { get; set; }
}
}
I do following to get the response:
var response = client.Execute<JsonResponseClass>(request);
var resData = response.Data;
How do I read/print values received from above? For example how do I print values verb and definition from the above deserialized response?
You're not supposed to nest the classes. Instead, add a property of each type to the root object's class.
public class JsonResponseClass
{
public Selector selector { get; set; }
public Points points { get; set; }
}
public class Selector
{
public static string verb { get; set; }
}
public class Points
{
public int definition { get; set; }
}
With that in place, the code works as expected:
var response = client.Execute<JsonResponseClass>(request);
var resData = response.Data;
var verb = resData.selector.verb;
var definition = resData.points.definition;
It's not clear what are you asking.
resData variable contains data from request stored in JsonResponseClass so you need to access it's fields like:
string verb = resData.verb;
Console.WriteLine(verb);
I am trying to post some data to my MVC 3 controller through a hidden text field that contains some JSON. I have that JSON passed in via string coursesList. Anyone have an idea why this is not working?
All I'm doing is making a byte [] out of the JSON string, writing it to a MemoryStream, and deserializing that stream -- or, attempting to. BookCourse bc always ends up with null properties.
Here's something like the JSON I would be using:
[{"coursesection":"1234","netlogon":"jsmith","label":"CRSE-1313 Generic Course Titling ~ Joe Smith"}]
And here's the object to be deserialized into:
using System.Runtime.Serialization;
namespace xxxx.Models
{
[DataContract]
public class BookCourse
{
[DataMember]
public string coursesection { get; set; }
[DataMember]
public string netlogon { get; set; }
[DataMember]
public string label { get; set; }
}
}
Finally, the controller action code to do it --
var byteArray = Encoding.ASCII.GetBytes(coursesList);
// Deserialize byte array to data type
var stream = new MemoryStream();
stream.Write(byteArray, 0, byteArray.Length);
var crs = new DataContractJsonSerializer(typeof(BookCourse));
stream.Position = 0;
// Read stream to object
ad.CourseSectionIDs = new List<int>();
try
{
var bc = (BookCourse) crs.ReadObject(stream);
while (bc.coursesection != null)
{
cs.AssociateCourseBook(bc.netlogon, bc.coursesection, ad.ISBN);
bc = (BookCourse)crs.ReadObject(stream);
}
}
catch (System.Runtime.Serialization.SerializationException e)
{
// Is this best practice for handling "none"?
}
Your JSON string represents a collection of BookCourse, not a single BookCourse. So adapt your code:
var serializer = new DataContractJsonSerializer(typeof(BookCourse[]));
and then:
var bookCourses = (BookCourse[])crs.ReadObject(stream);
or if you want to work with a single BookCourse you will need to change your JSON string and remove the wrapping square brackets which represent a collection.
Darin is correct, here is the change if you want to do it on a contract level.
[DataContract]
public class BookCourse
{
[DataMember]
public string coursesection { get; set; }
[DataMember]
public string netlogon { get; set; }
[DataMember]
public string label { get; set; }
}
[DataContract]
public class BookCourceCollection
{
[DataMember]
public List<BookCourse> Collection;
public static BookCourceCollection ReturnCollection(string jsonString)
{
MemoryStream ms;
BookCourceCollection collection;
using (ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(BookCourceCollection));
collection = ser.ReadObject(ms) as BookCourceCollection;
}
return collection;
}
}
Usage:
string jsonString = "Your JSON string from the front end";
var bookCourceObject = BookCourseCollection.ReturnCollection(jsonString);
foreach (BookCourse bookCourse in bookCourceObject.Collection)
{
cs.AssociateCourseBook(bookCourse.netlogon, bookCourse.coursesection, bookCourse.ISBN);
}