C# - Parsing JSON to multiple objects - c#

I'm trying to create multiple objects out of a JSON result.
My JSON looks like that:
EDIT
[{"quality":"hd","type":"video/mp4","width":1920,"height":1080,"link":"http://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=175&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:25+02:00","fps":23.98,"size":3113207678,"md5":"b6beed65b699df870e481045178accc5","link_secure":"https://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=175&oauth2_token_id=1040381751"},{"quality":"sd","type":"video/mp4","width":640,"height":360,"link":"http://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=164&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:05+02:00","fps":23.98,"size":536864946,"md5":"af227a5526af15d2bce6ac951d6cf06b","link_secure":"https://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=164&oauth2_token_id=1040381751"},{"quality":"sd","type":"video/mp4","width":960,"height":540,"link":"http://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=165&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:05+02:00","fps":23.98,"size":1242328160,"md5":"1963f908509b14fd7a40dc46bfa6c519","link_secure":"https://player.vimeo.com/external/255898412.sd.mp4?s=b51b55f6bd6e1af2a8f48571e5804d91e6a82533&profile_id=165&oauth2_token_id=1040381751"},{"quality":"hd","type":"video/mp4","width":1280,"height":720,"link":"http://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=174&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:05+02:00","fps":23.98,"size":1977386604,"md5":"af38f067bd39f4f5bb71bad72f925337","link_secure":"https://player.vimeo.com/external/255898412.hd.mp4?s=8766561d230749d75a0ddde2ddfbeb69e0e5198e&profile_id=174&oauth2_token_id=1040381751"},{"quality":"hls","type":"video/mp4","link":"https://player.vimeo.com/external/255898412.m3u8?s=f25b7114977a0c6b37739886da189051ed31999e&oauth2_token_id=1040381751","created_time":"2018-02-15T15:46:25+02:00","fps":23.98,"size":3113207678,"md5":"b6beed65b699df870e481045178accc5","link_secure":"https://player.vimeo.com/external/255898412.m3u8?s=f25b7114977a0c6b37739886da189051ed31999e&oauth2_token_id=1040381751"}]
it should be parsed into 3 objects.
I got a VideoFileModel.cs class that looks like that:
public partial class VideoFileModel
{
[JsonProperty("quality")]
public string Quality { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("width")]
public long? Width { get; set; }
[JsonProperty("height")]
public long? Height { get; set; }
[JsonProperty("link")]
public string Link { get; set; }
[JsonProperty("created_time")]
public System.DateTime CreatedTime { get; set; }
[JsonProperty("fps")]
public double Fps { get; set; }
[JsonProperty("size")]
public long Size { get; set; }
[JsonProperty("md5")]
public string Md5 { get; set; }
[JsonProperty("link_secure")]
public string LinkSecure { get; set; }
}
What I'm trying to do at the moment, is parsing it like that:
string json = Helpers.HTTPFetch(url, method, headers, body, contentType);
var result = JsonConvert.DeserializeObject<VideoFileModel>(json);
but I'm pretty sure it's not working, or at least not in the way I want it to work.
what should I change?

You should simply use List<> when deserializing :
var result = JsonConvert.DeserializeObject<List<VideoFileModel>>(json);
There are is a list of VideoFileModel in your JSON that you trying to deserialize into a single object.
Following gets deserialized:
UPDATE:
As per OP updated JSON. It still gets deserialized:

Related

Getting Errors when trying to Deserialize JSON object from API call in C#. (currency exchange)

My goal is to build an API that can load currency data from https://openexchangerates.org/ api into our SQLite database. I am able to get the JSON object formatted like this:
When i run the code below, it returns an errors. I am not sure how to resolve this. Just need to convert this JSON into a C# class without error.
Here's the custom C# object to mapped to JSON obj:
public class ExchangeRate
{
public string Disclaimer { get; set; }
public string License { get; set; }
public string Timestamp { get; set; }
public string Base { get; set; }
public string Rates { get; set; }
}
Here is the api call where its returning the error:
public static async Task<List> GetLatest(string url)
{
var client = new HttpClient();
string results = await client.GetStringAsync(url);
List<ExchangeRate> ratesList = JsonConvert.DeserializeObject<List<ExchangeRate>>(results);
return ratesList;
}
The example JSON is not a list, it's a single object, this is specified in the exception message
...because the type requires a JSON array
, otherwise it would have [ ] around it indicating an array (can be deserialized to list). Also, your model is flawed as Rates is not a string, but an object, and Timestamp is not a string but a long for the datetime as ticks. Change your model like so:
public class ExchangeRate
{
//decorate your properties since the json string uses lowercase
[JsonProperty("disclaimer")]
public string Disclaimer { get; set; }
[JsonProperty("license")]
public string License { get; set; }
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("rates")]
public Rates Rates { get; set; }
}
public class Rates
{
//create the properties for the Rates class
}
OR make the rates property a Dictionary<string, decimal>, NOTE: this could fail if any key is duplicated.
public class ExchangeRate
{
//decorate your properties since the json string uses lowercase
[JsonProperty("disclaimer")]
public string Disclaimer { get; set; }
[JsonProperty("license")]
public string License { get; set; }
[JsonProperty("timestamp")]
public long Timestamp { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("rates")]
public Dictionary<string, decimal> Rates { get; set; }
}
Change your code to this:
ExchangeRate rate = JsonConvert.DeserializeObject<ExchangeRate>(results);
Your C# class model does not match the incoming JSON data structure. Rates is an array of items, but you're treating it like a string in your C# model. Timestamp is a number but you're treating it like a string in your C# model.
public class ExchangeRate
{
public string Disclaimer { get; set; }
public string License { get; set; }
public int Timestamp { get; set; }
public string Base { get; set; }
public Dictionary<string, double> Rates { get; set; }
}

Converting JSON to Object fails - Cannot deserialize the current JSON object into System.Collections.Generic.List

I'm using the API of www.textlocal.in, which returns a JSON formatted object.
JSON
{
"warnings":[
{
"message":"Number is in DND",
"numbers":"917000000000"
}
],
"balance":900,
"batch_id":311110011,
"cost":1,
"num_messages":1,
"message":{
"num_parts":1,
"sender":"TXTLCL",
"content":"Test1"
},
"receipt_url":"",
"custom":"",
"inDND":[
"917000000000"
],
"messages":[
{
"id":"1350123781",
"recipient":918819437284
}
],
"status":"success"
}
My code with which I'm trying to parse the JSON:
private void button1_Click(object sender, EventArgs e)
{
var a = JsonConvert.DeserializeObject<List<jsonToObj[]>>(richTextBox1.Text);
}
public class jsonToObj
{
public warnings[] warnings { get; set; }
public int balance { get; set; }
public int batch_id { get; set; }
public int cost { get; set; }
public int num_messages { get; set; }
public message message { get; set; }
public string receipt_url { get; set; }
public string custom { get; set; }
public messages[] messages { get; set; }
public string status { get; set; }
}
public class warnings
{
public string message { get; set; }
public string numbers { get; set; }
}
public class messages
{
public string id { get; set; }
public int recipient { get; set; }
}
public class message
{
public int num_part { get; set; }
public string sender { get; set; }
public string content { get; set; }
}
I'm getting an exception with the following message:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON object (e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[WindowsFormsApp1.Form2+jsonToObj[]]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly. To fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be deserialized from a JSON
object. JsonObjectAttribute can also be added to the type to force it
to deserialize from a JSON object. Path 'warnings', line 1, position
12.'
First of all you have to figure out what your API returns.
Right now you're trying to parse a List of jsonToObj Arrays (List<jsonToObj[]>). You have to decide whether to use a jsonToObj[] or List<jsonToObj> or a simple jsonToObj which your API provides now:
var a = JsonConvert.DeserializeObject<jsonToObj>(richTextBox1.Text);
But this then throws:
JSON integer 918819437284 is too large or small for an Int32. Path 'messages[0].recipient', line 25, position 33."
So make sure you use a Long for that.
public class messages
{
public string id { get; set; }
public long recipient { get; set; }
}
Furthermore you can add inDND to your jsonToObj class if you need the info:
public class jsonToObj
{
...
public string[] inDND { get; set; }
...
}
Based on string you class structure should be like this :
public class Warning
{
public string message { get; set; }
public string numbers { get; set; }
}
public class Message
{
public int num_parts { get; set; }
public string sender { get; set; }
public string content { get; set; }
}
public class Message2
{
public string id { get; set; }
public long recipient { get; set; }
}
public class RootObject
{
public List<Warning> warnings { get; set; }
public int balance { get; set; }
public int batch_id { get; set; }
public int cost { get; set; }
public int num_messages { get; set; }
public Message message { get; set; }
public string receipt_url { get; set; }
public string custom { get; set; }
public List<string> inDND { get; set; }
public List<Message2> messages { get; set; }
public string status { get; set; }
}
It looks like your class structure is not proper, Make use of visual studio and generate C# class from json string and then using that generated class try to deserialize class.
Read : Visual Studio Generate Class From JSON or XML
I simulated your problem and made the following changes that worked:
Change the method that deserializes to this:
var a = JsonConvert.DeserializeObject<jsonToObj>(richTextBox1.Text);
The result of the JSON you receive is not a List, so it will not work to deserialize to List<>.
The recipient property of the messages class receives values larger than an integer, so it must be transformed into a long like this:
public long recipient { get; set; }
These changes solve your problem.
Looks like this is a very old post, still thought of answering.
First of all, your Json data is singular which means, either
var a = JsonConvert.DeserializeObject<List<jsonToObj[]>>(richTextBox1.Text);
or
var a = JsonConvert.DeserializeObject<List<jsonToObj>>(richTextBox1.Text);
may not work for you.
You can either try:
var a = JsonConvert.DeserializeObject<jsonToObj>(richTextBox1.Text);
or
enclose the data with [ and ], which would do the trick.
make sure your parsing single object vs list of objects.

Deserialize Object into a class does not work

I am trying to set a class for a token using DeserializeObject from the json object i get back from my api. However when i run the below code it sets all the values to null or 0, not the result i am getting from the api.
cs code
var resultString = await result.Content.ReadAsStringAsync();
var post = JsonConvert.DeserializeObject<Token>(resultString);
class
public class Token : ContentPage
{
public int StaffID { get; set; }
public string TokenApi { get; set; }
public string StaffForename { get; set; }
public string StaffSurname { get; set; }
public string StaffEmail { get; set; }
public int PrimaryStaffRoleID { get; set; }
}
JSON response
"{\"code\":201,\"status\":\"Success\",\"message\":\"Object found\",\"data\":{\"StaffID\":14,\"StaffSurname\":\"Test\",\"StaffForename\":\"Test\",\"StaffEmail\":\"test#test.com\",\"PrimaryStaffRoleID\":5,\"TokenApi\":\"testToken\"}}"
Firstly the data which you are trying to map is inside another property in your json called Data and secondly your json does not have a property with name Token
The problem actually is you are not using the correct type that reflects your json, means you don't have correct c# type which would get mapped to json, you can generate correct types using json2charp.com , the correct classes for it are :
public class Data
{
public int StaffID { get; set; }
public string StaffSurname { get; set; }
public string StaffForename { get; set; }
public string StaffEmail { get; set; }
public int PrimaryStaffRoleID { get; set; }
public string TokenApi { get; set; }
}
public class RootObject
{
public int code { get; set; }
public string status { get; set; }
public string message { get; set; }
public Data data { get; set; }
}
Now deserializing using RootObject as type parameter would work perfectly fine like:
var resultString = await result.Content.ReadAsStringAsync();
var post = JsonConvert.DeserializeObject<RootObject>(resultString);
A more good option is to use QuickType.IO which would even generate code for you in c# or any other language that they are supporting.
If you analyze the JSON that you posted, the object that you're trying to Deserialize is inside the "data" property of your json.
I suggest you creating a class to represent the JsonResponse with a Data property. This will be your Token
You are retrieved a string that match this object
public string code {get;set;}
public string Success {get;set;} ...
And Token is matching data in json, so
var post = JsonConvert.DeserializeObject<Token>(resultString.data);
would be better.

How to bind multilevel json data to a repeater in asp.net or converting json data to data table

I want to bind the Json data to the repeater I know only one process that is converting the Json data to data table and then binding data but here I am receiving multilevel json data i do't know how to convert them to data table
input json data:
{"apiAvailableBuses":
[{"droppingPoints":null,"availableSeats":40,"partialCancellationAllowed":false,"arrivalTime":"01:00 AM","cancellationPolicy":"[{\"cutoffTime\":\"1\",\"refundInPercentage\":\"10\"},{\"cutoffTime\":\"2\",\"refundInPercentage\":\"50\"},{\"cutoffTime\":\"4\",\"refundInPercentage\":\"90\"}]","boardingPoints":[{"time":"07:40PM","location":"K.P.H.B,Beside R.S Brothers","id":"2238"}],"operatorName":"Apple I Bus","departureTime":"8:00 PM","mTicketAllowed":false,"idProofRequired":false,"serviceId":"6686","fare":"1000","busType":"Hi-Tech A/c","routeScheduleId":"6686","commPCT":9.0,"operatorId":203,"inventoryType":0},
{
"droppingPoints":null,"availableSeats":41,"partialCancellationAllowed":false,"arrivalTime":"06:00 AM","cancellationPolicy":"[{\"cutoffTime\":\"1\",\"refundInPercentage\":\"10\"},{\"cutoffTime\":\"2\",\"refundInPercentage\":\"50\"},{\"cutoffTime\":\"4\",\"refundInPercentage\":\"90\"}]","boardingPoints":[{"time":"08:00PM","location":"Punjagutta,","id":"2241"}],"operatorName":"Royalcoach Travels","departureTime":"8:00 PM","mTicketAllowed":false,"idProofRequired":false,"serviceId":"6736","fare":"800","busType":"VOLVO","routeScheduleId":"6736","commPCT":9.0,"operatorId":243,"inventoryType":0}
I am trying to convert it to data table by
public void getavailablebuses()
{
string url = string.Format(HttpContext.Current.Server.MapPath("files/getavailablebuses.json"));
using (WebClient client = new WebClient())
{
string json = client.DownloadString(url);
var result = JsonConvert.DeserializeObject<RootObject>(json);
string mm = JObject.Parse(json).SelectToken("apiAvailableBuses").ToString();
// var boardingpoint = JObject.Parse(mm).SelectToken("boardingPoints").ToString();
var Availablebuses = JObject.Parse(json).SelectToken("apiAvailableBuses").ToString();
DataTable dt = (DataTable)JsonConvert.DeserializeObject(Availablebuses, (typeof(DataTable)));
}
public class apiresult
{
public string message { get; set; }
public string success { get; set; }
}
public class RootObject
{
public apiresult apiStatus;
public List<apiAvailableBuses> apiAvailableBuses{ get; set; }
// public string apiAvailableBuses { get; set; }
}
public class apiAvailableBuses
{
public string serviceId { get; set; }
public string fare { get; set; }
public string busType { get; set; }
public string departureTime { get; set; }
public string operatorName { get; set; }
public string cancellationPolicy { get; set; }
public List<boardingpoints> boardingpoints { get; set; }
public string droppingPoints { get; set; }
public string inventoryType { get; set; }
public string routeScheduleId { get; set; }
public int availableSeats { get; set; }
public string arrivalTime { get; set; }
public Boolean idProofRequired { get; set; }
public Boolean partialCancellationAllowed { get; set; }
public int operatorId { get; set; }
public double commPCT { get; set; }
public string mTicketAllowed { get; set; }
}
public class boardingpoints
{
public string location { get; set; }
public string id { get; set; }
public string time { get; set; }
}
public class cancellationPolicy
{
public string cutoffTime { get; set; }
public string refundInPercentage { get; set; }
}
Here in the data table I am unable to get the boarding points, dropping points and cancellation policy
if I load cancellation policy as list or JObject I am getting error
so here I am loading cancellation policy as string.
but I am unable to load boarding points and dropping points.
Please help with this I am scratching my head from two days. Thanks in advance
"I know only one method to bind data to a repeater i.e data table." So this is a perfect opportunity to learn other ways, wouldn't you say?
Why don't you work with the result of JsonConvert.DeserializeObject<RootObject>(json);? This is a RootObject that has a property called apiAvailableBuses which seems to be exactly what you need to bind to your repeater, no?
By the way, a bit of code review:
apiresult and apiAvailableBuses violate Microsoft's rules WRT class names: those should be in PascalCase. Same for the properties of apiresult, e.g. message and success. Same for the properties of apiAvailableBuses.
RootObject has a public field: apiStatus. That probably needs to be a a property with a getter/setter.
Moreover, apiAvailableBuses is plural, which is incorrect, since the data therein is of only one bus. Same for boardingpoints: the class contains data for a single point, not multiple.
Be consistent: if you use string, then also use bool and not Boolean.

Json response to class mapping Restsharp deserializing

I am using RestSharp to consume a restful webservice. I am using the built in Json Deserializer to deserialize the response.
This is the response.
[{"id":"1","latitude":"18.0155848","longitude":"-77.4988293","rating":"1","streetid":"1","username":"joel","verified":"1"},{"id":"2","latitude":"18.0155892","longitude":"-77.498774","rating":"1","streetid":"2","username":"joel","verified":"0"},{"id":"3","latitude":"18.0227736","longitude":"-77.4980039","rating":"1","streetid":"3","username":"joel","verified":"0"}]
These are the models its being mapped to.
List<Pothole> list = new List<Pothole>();
public class Pothole
{
//getters and setters for the attributes of Pothole Model
public long Id { get; set;}
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Rating{ get;set;}
public long StreetId { get; set; }
public string Username { get; set; }
public bool Verified { get; set; }
}
However when I make the call the data is not being deserialized.I am wondering if there is a problem with the json response to the class mapping. I am mapping the response to a list of potholes due to an array of pothole objects being returned. I check the HTTP status code and the content of the response so the data is being returned, its just the deserializing causing a problem.
Try this:
public class Pothole
{
public string id { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public string rating { get; set; }
public string streetid { get; set; }
public string username { get; set; }
public string verified { get; set; }
}
C# is case sensitive and so the reflection that takes place in populating the C# object will look for properties with names EXACTLY like those in the JSON string.
Also, if you're using Visual Studio 2012 SP 1 you can actually paste JSON text as a C# class. Pretty handy.
Or you can also use : Json2Csharp
generate c# classes from json
Late to the party but I thought I'd throw in my $0.02. I am using an unmodified version of RestSharp.Portable 1.6.2 Xamarin PCL
I have json as follows:
{"blah":{"iPAddress":"10.1.1.x","cPU":"1 vCPU","dNSName":"blah.blah.com"}}
with the class below, the deserialzation does not work for CPU, works for DSName, and IPAddress though.
public class Blah
{
public string CPU { get; set; }
public string DNSName { get; set; }
public string IPAddress { get; set; }
}
However if I change CPU to cPU it works fine.
public class Blah
{
public string cPU { get; set; }
public string DNSName { get; set; }
public string IPAddress { get; set; }
}
So, feels like a bug, just wanted to contribute.

Categories

Resources