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

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

Related

JSON with Array Respone from API

i have a HTTPclient and im sending request to a Server.
The response from the server is a JSON. In this Json is also an array.
I want do display the information from the JSON in the consol.
I get all information from the JSON, but i dont get the array displayed in my console.
The JSON looks like this:
{
"Name1": "Karl",
"Name2": "Peter",
"Name3": "Wilhelm",
"PreNames": {
"PreName": "Werner",
"PreName2": "Josef"
}
}
So now my Code so far:
public class PreNames //for Array
{
public string PreName { get; set; }
public string PreName2{ get; set; }
}
public class Names//for JSON
{
public string Name1{ get; set; }
public string Name2{ get; set; }
public string Name3{ get; set; }
}
And my Main:
if (Response().IsSuccessStatusCode)
{
var namesJ= Response().Content.ReadAsAsync<IEnumerable<Names>>().Result;
var preNamesJ= await Response().Content.ReadAsAsync<List<PreNames>>();
foreach (var a in namesJ)
{
Console.WriteLine("Name1: {0}", a.Name1);
foreach(var b in preNamesJ)
{
Console.WriteLine("{0}", b.PreName);
}
}
So in the console are all names displayed, but not the PreNames so i cant get the PreNames from the array in the JSON...
I Hope somebody could help me :)
Add the PreNames property to your Names class and only read one time.
public class Names//for JSON
{
public string Name1{ get; set; }
public string Name2{ get; set; }
public string Name3{ get; set; }
public List<PreNames> PreNames { get; set;}
}
Once you read in the result one time, you can access the elements via the main object
var namesJ= Response().Content.ReadAsAsync<Names>().Result;
foreach(var names in namesJ.PreNames)
{
Console.WriteLine(names.PreName);
}
updated
Since you changed the json and made PreNames just an object instead of an array, simply access the property of related object.
public class Names//for JSON
{
public string Name1{ get; set; }
public string Name2{ get; set; }
public string Name3{ get; set; }
public PreNames PreNames { get; set;}
}
var namesJ= Response().Content.ReadAsAsync<Names>().Result;
Console.WriteLine(namesJ.PreNames.Name);
#Leonc443, Here is a working code
using Newtonsoft.Json; //add this nuget package
using System;
namespace ConsoleApp
{
class Program
{
public static void Main(string[] args)
{
string json = #"{
'Name1': 'Karl',
'Name2': 'Peter',
'Name3': 'Wilhelm',
'PreNames': {
'PreName': 'Werner',
'PreName2': 'Josef'
}
}"; // data received from api
var names = JsonConvert.DeserializeObject<Names>(json);
Console.WriteLine(names.Name1); // Karl
Console.WriteLine(names.Name2); //Peter
Console.WriteLine(names.Name3); //Wilhelm
Console.WriteLine(names.PreNames.PreName); //Werner
Console.WriteLine(names.PreNames.PreName2); // Josef
}
}
public class Names
{
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
public PreNames PreNames { get; set; }
}
public class PreNames
{
public string PreName { get; set; }
public string PreName2 { get; set; }
}
}
Please let me know if this helps
In case your Json looks like:
{
"Name1": "Karl",
"Name2": "Peter",
"Name3": "Wilhelm",
"PreNames": {
"PreName": "Werner",
"PreName2": "Josef"
}
}
If the PreNames are in the Names, you shuld add a PreNames field to the Names Class.
public class Names
{
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
public PreNames PreNames { get; set; }
}
Then you can read the inner PreNames:
foreach (var b in a.Prenames) {
Console.WriteLine(b.PreName);
}
But I'm not sure if I understand your question.
I don't have sufficient reputation to comment, so... I'll give it a try.
Edited after proper json updated in Answer.
Change your class Names
public class Names
{
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
public PreNames PreNames { get; set; }
}
Then deserialize it with JsonConvert
var json = await Response().Content.ReadAsStringAsync();
var names = JsonConvert.DeserializeObject<Names>(json);
Then access data
Console.WriteLine($"Name 1: {names.Name1}");
Console.WriteLine($"Prename 1: {names.PreNames.PreName}");

Not able validate data condition based on the json element attribute value from a json using c#

I have a json file, where i have to validate a json attribute element value based on another json element attribute value. But if there json elements with the same name. It always takes the last value always instead of parsing the json data fully. Please guide me.
Below the sample json file
{
"PLMXML":{
"language":"en-us",
"author":"Developer",
"date":"2020-05-22",
"traverseRootRefs":"#id6",
"Operation":{
"id":"id21",
"subType":"BS4_BaOP",
"catalogueId":"70700000209604"
},
"Operation":{
"id":"id28",
"subType":"BS4_BaOP",
"catalogueId":"70700000209603"
},
"OperationRevision":{
"id":"id6",
"subType":"BS4_BaOPRevision",
"masterRef":"#id21",
"revision":"A1"
}
}
}
And below the code which im trying to use
public void Readjsonfile(string jsondata)
{
var message = JsonConvert.DeserializeObject<plmxmldatamodel>(jsondata);
if (String.Equals(message.PLMXML.traverseRootRefs.Substring(1), message.PLMXML.OperationRevision.id))
{
Console.WriteLine("Condtion1");
if (String.Equals(message.PLMXML.OperationRevision.masterRef.Substring(1), message.PLMXML.Operation.id))
{
Console.WriteLine("Condition_2");
//Do something based on the condtion
}
}
}
public class Operation
{
public string id { get; set; }
public string subType { get; set; }
public string catalogueId { get; set; }
}
public class OperationRevision
{
public string id { get; set; }
public string subType { get; set; }
public string masterRef { get; set; }
}
public class PLMXML
{
public string language { get; set; }
public string author { get; set; }
public string date { get; set; }
public string traverseRootRefs { get; set; }
public Operation Operation { get; set; }
public OperationRevision OperationRevision { get; set; }
}
public class plmxmldatamodel
{
public PLMXML PLMXML { get; set; }
}
When i try to dedug this in the second if condtion, the value for message.PLMXML.Operation.id is always id28 , because of which second if condition fails. While the first if condition is passed as there is only one message.PLMXML.OperationRevision.id. i wanted behaviour where it would check complete json data and check if message.PLMXML.Operation.id with value id21 is present or not , So my data gets passed. Please kindly guide me here.I am very new to C# here.
From my observation you have couple of issues.
What happen you have double keys, and your parser taking the last value not the first one.
First of all your json should be corrected. I assume you have access to change your json and operation should be an array like follow:
{
"PLMXML":{
"language":"en-us",
"author":"Developer",
"date":"2020-05-22",
"traverseRootRefs":"#id6",
"Operations":[
{
"id":"id21",
"subType":"BS4_BaOP",
"catalogueId":"70700000209604"
},
{
"id":"id28",
"subType":"BS4_BaOP",
"catalogueId":"70700000209603"
}
],
"OperationRevision":{
"id":"id6",
"subType":"BS4_BaOPRevision",
"masterRef":"#id21",
"revision":"A1"
}
}
}
When array in place than use an online tool like to validate your json and use this tool to create a model.
Your model will be like this:
public partial class PlmxmlDataModel
{
[JsonProperty("PLMXML")]
public Plmxml Plmxml { get; set; }
}
public partial class Plmxml
{
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("author")]
public string Author { get; set; }
[JsonProperty("date")]
public DateTimeOffset Date { get; set; }
[JsonProperty("traverseRootRefs")]
public string TraverseRootRefs { get; set; }
[JsonProperty("Operations")]
public Operation[] Operations { get; set; }
[JsonProperty("OperationRevision")]
public OperationRevision OperationRevision { get; set; }
}
public partial class OperationRevision
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("subType")]
public string SubType { get; set; }
[JsonProperty("masterRef")]
public string MasterRef { get; set; }
[JsonProperty("revision")]
public string Revision { get; set; }
}
public partial class Operation
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("subType")]
public string SubType { get; set; }
[JsonProperty("catalogueId")]
public string CatalogueId { get; set; }
}
And your method like this:
public void Readjsonfile(string jsondata)
{
var message = JsonConvert.DeserializeObject<PlmxmlDataModel>(jsondata);
if (String.Equals(message.Plmxml.TraverseRootRefs.Substring(1), message.Plmxml.OperationRevision.Id))
{
Console.WriteLine("Condtion1");
if (String.Equals(message.Plmxml.OperationRevision.MasterRef.Substring(1), message.Plmxml.Operations[0].Id))
{
Console.WriteLine("Condition_2");
//Do something based on the condtion
}
}
}
Now in your method I am looking for array index 0 with contain id 28, but if you are look for id 28 in any of the array then you can do some thing like:
if (message.Plmxml.Operations.Any(e => e.Id == message.Plmxml.OperationRevision.MasterRef.Substring(1)))

Can't deserialize an indexed name value pair child node C#

I'm running into an issue when I am trying to deserialize a webAPI GET call that returns a JSON object. The issue being one particular property is always null after being deserialized.
The JSON object looks like this:
{
"status":"OK",
"masterlist":{
"session":{
"session_id":intValue,
"session_name":"stringValue"
},
"0":{
"bill_id":intValue,
"number":"stringValue",
"change_hash":"stringValue",
"url":"stringValue",
"status_date":"dateValue",
"status":"stringValue",
"last_action_date":"dateValue",
"last_action":"stringValue",
"title":"stringValue",
"description":"stringValue"
},
"1":{
"bill_id":intValue,
"number":"stringValue",
"change_hash":"stringValue",
"url":"stringValue",
"status_date":"dateValue",
"status":"stringValue",
"last_action_date":"dateValue",
"last_action":"stringValue",
"title":"stringValue",
"description":"stringValue"
},
"2":{
"bill_id":intValue,
"number":"stringValue",
"change_hash":"stringValue",
"url":"stringValue",
"status_date":"dateValue",
"status":"stringValue",
"last_action_date":"dateValue",
"last_action":"stringValue",
"title":"stringValue",
"description":"stringValue"
}
}
}
As you can see the second property of masterlist isn't an array, that would make life too easy... But it looks more like a collection of name/value pairs. I have reviewed This post and the associated one listed within but they both pertain to if the name/value pair where at the root level where mine is not.
My method that I am using to deserialize is:
BillMaster billMasterList = new BillMaster();
using (HttpClient client = new HttpClient())
{
string json = Get("&op=getMasterList&state=TN");
billMasterList = JsonConvert.DeserializeObject<BillMaster>(json);
}
And the model classes the deserializer is binding to:
public class BillMaster
{
public string Status { get; set; }
public BillMasterList masterlist { get; set; }
}
public class BillMasterList
{
public BillMasterList_Session session { get; set; }
public Dictionary<int, BillMasterList_Array> BillMasterList_Array { get; set; }
}
public class BillMasterList_Array
{
public int bill_id { get; set; }
public string number { get; set; }
public string change_hash { get; set; }
public string url { get; set; }
public string status_date { get; set; }
public string status { get; set; }
public string last_action_date { get; set; }
public string last_action { get; set; }
public string title { get; set; }
public string description { get; set; }
}
When I run the code I don't throw any errors and I have values in my object except for BillMasterList_Array, that is always null. I'm obviously not doing something right but what it is alludes me.

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.

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