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

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.

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

How do I parse this JSON data in C# and would it be more benefical to simply switch over to javascript?

I'm looking to parse this JSON and I've had nothing but problems. The link to the JSON is here. I'm trying to access the "href" field. While writing this up, I realized that that the data field is actually an array so that is part of my problem.
class Program
{
static void Main(string[] args)
{
var json = System.IO.File.ReadAllText(#"C:\Users\...\file.json");
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);
var x = myDeserializedClass.result.extractorData.data;
Console.Write(x.ToString());
}
public class Newcolumn
{
public string text { get; set; }
public string xpath { get; set; }
public string href { get; set; }
public string filepath { get; set; }
public string fileMimeType { get; set; }
public int fileTotalBytes { get; set; }
public string fileLastModifiedTime { get; set; }
}
public class Group
{
public List<Newcolumn> Newcolumn { get; set; }
}
public class Datum
{
public List<Group> group { get; set; }
}
public class ExtractorData
{
public string url { get; set; }
public List<Datum> data { get; set; }
}
public class PageData
{
public int statusCode { get; set; }
public long timestamp { get; set; }
}
public class Inputs
{
public string _url { get; set; }
}
public class Result
{
public ExtractorData extractorData { get; set; }
public PageData pageData { get; set; }
public Inputs inputs { get; set; }
public string taskId { get; set; }
public long timestamp { get; set; }
public int sequenceNumber { get; set; }
}
public class Root
{
public string url { get; set; }
public Result result { get; set; }
}
}
This ends up returning: System.Collections.Generic.List`1[ConsoleApp3.Datum]
I notice that the field name data actually turns into an array though I'm not sure how to structure that. data.[0].new Column.[0].group.etc... does not work obviously. The space in the "new Column" field is also problematic. Additionally, when I debug and look at the JSON viewer, the "new column field is null. I also tried this code:
public static void Main()
{
var json = System.IO.File.ReadAllText(#"C:\Users\...\file.json");
dynamic stuff = JsonConvert.DeserializeObject(json);
var a = stuff.result.extractorData.data;
string b = a.ToString();
Console.WriteLine(b);
Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
This actually does return the data field object however, if I do stuff.result.extractorData.data.group; I get this:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
HResult=0x80131500
Message='Newtonsoft.Json.Linq.JArray' does not contain a definition for 'group'
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
I assume that this is probably because of the array contained within the data field, regardless the "new Column' field is also an issue with this method due to the space.
in your above code
public class ExtractorData
{
public string url { get; set; }
public List<Datum> data { get; set; }
}
where data is List and you are trying to access as string
Console.Write(x.ToString());
in data variable Datum is List ( where your variable have multiple Data) and in every element there is a List. (Nestest List Concept Applied in This JSON)
Try to Add Break Point on below Line and check the line by line Excution of Code.
var a = stuff.result.extractorData.data;
After Looking Your JSON File Image Try This Code
Console.Write(a.FirstOrDefault()?.group.FirstOrDefault()?.Newcolumn.FirstOrDefault()?.href);

nested json deserialization - need another set of eyes

I have been trying to get this json to deserialize for two days now using RestSharp. I have gone through the RestSharp github site, looked at countless examples, and spent much time here on Stack Overflow to try and find the answer to no avail. My code had previously worked perfectly but the vendor changed their API version and I was forced to do an update to keep using the application for my legal practice. My json is as follows(client info has been removed and replaced with generic info):
{
"data":[
{
"id":1035117666,
"client":
{
"id":905422394,
"name":"client1"
},
"display_number":"11-00012",
"description":"General",
"practice_area":
{
"id":4269978,
"name":"Business"
},
"status":"Open",
"open_date":"2011-12-14",
"close_date":null,
"billing_method":"hourly"
},
{
"id":1035117768,
"client":
{
"id":905422506,
"name":"client2"
},
"display_number":"12-00037",
"description":"HOA",
"practice_area":
{
"id":4269978,
"name":"Business"
},
"status":"Open",
"open_date":"2012-08-07",
"close_date":null,
"billing_method":"hourly"
}
],
"meta":
{
"paging":
{
"next":"https://app.goclio.com/api/v4/matters.json?fields=id%2C+client%7Bid%2C+name%7D%2C+display_number%2C+description%2C+practice_area%7Bid%2C+name%7D%2C+status%2C+open_date%2C+close_date%2C+billing_method&limit=2&page_token=BAh7BjoLb2Zmc2V0aQc%3D--b1ea3eba20c8acefbcdfc7868debd1e0ee630c64&status=Open"
},
"records":91
}
}
I built the following schema within my c# code:
public class MatterList
{
public List<Matter> matters { get; set; }
public Meta meta { get; set; }
}
public class Meta
{
public Paging paging { get; set; }
public int records { get; set; }
}
public class Paging
{
public string previous { get; set; }
public string next { get; set; }
}
[DeserializeAs(Name = "data")]
public class Matter
{
public int id { get; set; }
public Client client { get; set; }
public string display_number { get; set; }
public string description { get; set; }
public PracticeArea practice_area { get; set; }
public string status { get; set; }
public DateTime open_date { get; set; }
public DateTime close_date { get; set; }
public string billing_method { get; set; }
public string type = "matter";
}
public class PracticeArea
{
public int id { get; set; }
public string name { get; set; }
}
public class Client
{
public int id { get; set; }
public string name { get; set; }
}
When I run the RestSharp deserialize method I am sending the result to an object of type MatterList using the following line of code
MatterList matterList = jsonHandler.Deserialize<MatterList>(response);
I have so far attempted to deserialize without the Meta or Paging POCO classes with the accompanying change to the MatterList class (taking out the Meta property).
I have tried with and without the [DeserializeAs(Name="data")] directive.
I have tried to set the RootElement of the json response prior to deserialization.
I have tried to shorthand the deserialization by combining it with the Execute request code
IRestResponse<MatterList> matterList = client.Execute<MatterList>(request);
I have created a container class called MatterContainer which I placed between MatterList and Matter classes in the schema:
public class MatterList
{
public List<MatterContainer> matters { get; set; }
}
public class MatterContainer
{
public Matter matter { get; set; }
}
public class Matter
{
public int id { get; set; }
public Client client { get; set; }
public string display_number { get; set; }
public string description { get; set; }
public PracticeArea practice_area { get; set; }
public string status { get; set; }
public DateTime open_date { get; set; }
public DateTime close_date { get; set; }
public string billing_method { get; set; }
public string type = "matter";
}
I know I am getting the json response back from the server correctly so my request is proper and MatterList is not null after deserialization. The problem is that I cannot get the deserialization to actually populate the List matters within the MatterList class.
I have been looking at this off and on for two days and cannot get past this hurdle. If anyone sees what I did wrong I would greatly appreciate the insight, I am at a point where I cannot progress further with my application.
Thanks!
I think your [DeserializeAs(Name = "data")] attribute is in the wrong place. Try putting it in the root class instead:
public class MatterList
{
[DeserializeAs(Name = "data")]
public List<Matter> matters { get; set; }
public Meta meta { get; set; }
}
alternatively, try renameing that property to data

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.

Setting up a class to contain a list of objects

I am setting a class in C# to hold a response that I will be receiving from a web service call. I'm using RestSharp to handle the calling / parsing of the JSON data.
The web service documentation describes the response as:
OUTPUT: JSON object similar to example below.
{
"response":"[success] or [failed]",
"messages":"Process succeeded.",
"logonkey":"[logon key]",
"tokenkey":"[security token]",
"reccount":"1",
"filelist":
{
"fileid":"12345",
"status":"N",
"filename":"data.tar",
"fulfilled":"2012-06-15"
}
}
My question is how can I define the filelist array element in my class?
I was thinking something like this:
public class Files
{
public string Response { get; set; }
public string Messages { get; set; }
public string LogonKey { get; set; }
public string TokenKey { get; set; }
public int RecordCount { get; set; }
public List<FileList>
}
public class FileList
{
public string FileID { get; set; }
public string Status { get; set; }
public string Filename { get; set; }
public DateTime Fulfilled { get; set; }
}
However, I'm having a problem with the "public List" statement.
Any suggestions on the best way to handle this scenario would be appreciated.
Also you forgot to give it a name, for example try this
public List<FileList> MyFavouriteList {get;set;}.
A proprety is declared like this "access modifier", "Type", "identifier(or name)", "getter and setter".
The filelist in JSON sample doesn't look like list of objects. Instead it is a single object.
You could try,
public class Files
{
public string Response { get; set; }
public string Messages { get; set; }
public string LogonKey { get; set; }
public string TokenKey { get; set; }
public int RecordCount { get; set; }
public FileList File {get; set; }
}
If you are sure the filelist in JSON is really list of object, you could try,
public List<FileList> Files = new List<FileList>();

Categories

Resources