Getting values from nested object with C# - c#

I have this object and I am trying to get the lat and lon values in the location field within telemetry. I am new to c#, but know python. What I would have done in python was:
item.details["telemetry"].location.lat
Can someone please show me how this is supposed to be done in c#?
"details": {
"asset": {
"id": "5ca12266-35fe-4f75-8593-588fba777d6d",
"name": "ZS-FOO"
},
"assetType": {
"id": "87bc0a83-045d-4810-888c-237b5ef17ea4",
"name": "FOO"
},
"telemetry": {
"flags": 0,
"ownerId": "4adc68e4-7113-4b0f-8aba-dea213e8a948",
"originId": "09e0021f-9c54-425b-ae23-cbfe3c786a66",
"type": "telemetry",
"linked": ["5ca12266-35fe-4f75-8593-588fba777d6d"],
"date": "2017/01/20 13:46:01",
"received": "2017/01/20 13:46:21",
"active": true,
"location": {
"lon": 116072,
"lat": -87448,
"speed": 74,
"altitude": 98.228,
"heading": 56,
"accuracy": 5,
"age": 0
},
"zones": [],
"routes": null,
"state": null,
"telemetry": {
"msg_type": 0,
"vert_speed": 1.2,
"hdop": 1.65,
"vdop": 3.51,
"movement": 1,
"odo_counter": 162704.12317,
"hours_00_counter": 1027.885442,
"idle_counter": 0
},
"io": null,
"spd": null,
}
}

As i said in comment download Newtonsoft.Json
JObject data= JObject.Parse(data);
JToken details = data["details"];
string lat = details["telemetry"]["location"]["lat"].ToString();

Firstly, generate models for your data. You can do it manually by creating classes or if you are in Visual Studio, this would be helpful:
Edit=> Paste Special=> Paste JSON as class. This will generate the classes for you.
Afterwords, go with Json.NET or any other library to parse your file:
public class Program{
static void Main (string[] args){
var client = new WebClient();
var jsonString = client.DownloadString("Your link to Json file");
var response= JsonConvert.DeserializeObject</*Json Class*/>(jsonString);
//Now you can retrieve the data like this:
var lat = response.details.telemetry.location.lat;
}
}
Don't forget to import:
using System.Net;
using Newtonsoft.Json;

Related

Convert HTTPResponse Message (Json)

I am trying to convert the content of a response message to a list of items contained within the response message and keep running into issues, the returned json looks like this:
Jason output
Here is the whole returned response content:
{
"Version": 1,
"Result": "Success",
"Data": {
"Tasks": [
{
"Oid": "f70b1a46-690f-4637-886b-f90f035a11e8",
"CreatedOn": "2022-07-15T00:07:41.553Z",
"ChangedOn": "2022-07-15T03:39:58.373Z",
"Subject": "233817 3693 Range Rd",
"Description": "",
"Comment": "",
"IsStarted": true,
"IsFinished": true,
"IsFinalAppointment": false,
"ScheduledOn": "2022-07-15T09:37:41.553",
"ProductionDeadline": "0001-01-01T00:00:00",
"ScheduledStart": "2022-07-15T09:45:00",
"ScheduledEnd": "2022-07-15T09:50:00",
"RealStart": "2022-07-15T09:45:00",
"RealEnd": "2022-07-15T09:50:00",
"CalculatedSeconds": 300.0000,
"IdleSeconds": 0,
"ScheduledDuration": "PT5M",
"RealDuration": "PT5M",
"Status": 2,
"PercentComplete": 100,
"HasFinishedItems": true,
"IsCustomTask": false,
"AppointmentType": "OrderSpecificAppointment",
"OrderItemCount": 31,
"OrderItemPartsCount": 56,
"MaterialUsageTotal": 58.3280000000,
"MaterialUsageTotalConverted": 58.328,
"MaterialUsageNet": 46.9659000000,
"MaterialUsageNetConverted": 46.9659,
"MaterialUsageScrap": 11.3621000000,
"MaterialUsageScrapConverted": 11.3621,
"MaterialUsageTotalWeight": 263.4676,
"MaterialUsageTotalWeightConverted": 263.4676,
"MaterialUsageNetWeight": 212.1449000000,
"MaterialUsageNetWeightConverted": 212.14490,
"MaterialUsageScrapWeight": 51.3227000000,
"MaterialUsageScrapWeightConverted": 51.32270,
"Station": {
"_Value": "Centurio",
"oid": "f7f3c5fe-49f0-4a9a-b366-29c4ab990fc7"
},
"Materials": [
{
"_Value": "STEALTH MATTE .55 (MONUMENT†)",
"oid": "4889a4f2-75c6-4fb2-b57d-d393ff495ef1",
"externalID": "161539"
}
],
"MaterialCoils": [],
"MaterialDimensions": [],
"PreviousDependencies": [],
"NextDependencies": [
{
"_Value": "",
"oid": "4699df81-4d5c-456c-904d-389a08f60a82",
"start": "2022-07-17T03:37:00",
"station": "Unallocated Folding Station"
}
]
},
{
"Oid": "4699df81-4d5c-456c-904d-389a08f60a82",
"CreatedOn": "2022-07-15T00:07:41.567Z",
"ChangedOn": "2022-07-15T08:27:19.297Z",
"Subject": "233817 3693 Range Rd",
"Description": "",
"Comment": "",
"IsStarted": true,
"IsFinished": true,
"IsFinalAppointment": true,
"ScheduledOn": "2022-07-15T09:37:41.567",
"ProductionDeadline": "0001-01-01T00:00:00",
"ScheduledStart": "2022-07-17T03:37:00",
"ScheduledEnd": "2022-07-17T06:33:00",
"RealStart": "2022-07-17T03:37:00",
"RealEnd": "2022-07-17T06:33:00",
"CalculatedSeconds": 10560.0000,
"IdleSeconds": 0,
"ScheduledDuration": "PT2H56M",
"RealDuration": "PT2H56M",
"Status": 2,
"PercentComplete": 100,
"HasFinishedItems": true,
"IsCustomTask": false,
"AppointmentType": "OrderSpecificAppointment",
"OrderItemCount": 31,
"OrderItemPartsCount": 56,
"MaterialUsageTotal": 46.9659000000,
"MaterialUsageTotalConverted": 46.9659,
"MaterialUsageNet": 46.9659000000,
"MaterialUsageNetConverted": 46.9659,
"MaterialUsageScrap": 0.0000000000,
"MaterialUsageScrapConverted": 0.0,
"MaterialUsageTotalWeight": 212.1449,
"MaterialUsageTotalWeightConverted": 212.1449,
"MaterialUsageNetWeight": 212.1449000000,
"MaterialUsageNetWeightConverted": 212.14490,
"MaterialUsageScrapWeight": 0.0000000000,
"MaterialUsageScrapWeightConverted": 0.00000,
"Station": {
"_Value": "Unallocated Folding Station",
"oid": "7ce5334a-b05c-4511-be7b-1a83d2bf8d4c"
},
"Materials": [
{
"_Value": "STEALTH MATTE .55 (MONUMENT†)",
"oid": "4889a4f2-75c6-4fb2-b57d-d393ff495ef1",
"externalID": "161539"
}
],
"PreviousDependencies": [
{
"_Value": "",
"oid": "f70b1a46-690f-4637-886b-f90f035a11e8",
"start": "2022-07-15T09:45:00",
"station": "Centurio"
}
],
"NextDependencies": []
}
]
},
"Details": ""
}
I wish to extract each task from the "Tasks" element into a list (I have created a class to hold each Task element). So far my code looks like this:
public async void AppointmentsAsync(int taskScheduleID)
{
HttpResponseMessage taskList;
using (RevSchedDataContext context = new RevSchedDataContext())
{
string TimePrint = ConfigurationManager.AppSettings["TimePrint"];
schedule = (from s in context.TaskSchedules.Where(x => x.TaskScheduleID == taskScheduleID) select s).FirstOrDefault();
client.BaseAddress = new Uri("http://bendex.revroof.com.au/microsea/BendexRevBend/import/1.0/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
taskList = await client.GetAsync($"{client.BaseAddress}GetOrderScheduledTasksListJson?did=233817");
var products = await taskList.Content.ReadAsStringAsync();
var mtLists = JsonConvert.DeserializeObject<BendexTaskList>(products);
}
}
When putting a breakpoint on mtLists line and stepping mtLists never get populated.
Regards
Peter
I have found a solution to my problem thanks to the following site: https://json2csharp.com/
This enabled me to create the correct required classes to deserialize the json output in the format required to process.
New calling code:
Root scheduledTaskList = JsonConvert.DeserializeObject<Root>(products);
foreach(var tsk in scheduledTaskList.Data.Tasks)
{
//ToDo: pull required data and update table
}
Regards
Peter

C# Get Json sub values

I have a API response has a structure like shown below. How can I get the values from this Json string?
[
{
"id": xxx,
"profileId": xxx,
"recipientId": xxx,
"creationTime": "xxxx",
"modificationTime": "xxxx",
"active": true,
"eligible": true,
"balances": [
{
"balanceType": "AVAILABLE",
"currency": "EUR",
"amount": {
"value": 55555,
"currency": "EUR"
},
"reservedAmount": {
"value": 0,
"currency": "EUR"
},
"bankDetails": {
"id": xxx,
"currency": "EUR",
"bankCode": "code",
"accountNumber": "account number",
"swift": "swift",
"iban": "iban",
"bankName": "bankName",
"accountHolderName": "accountHolderName",
"bankAddress": {
"addressFirstLine": "bankAddress",
"postCode": "xxxxx",
"city": "xxxxx",
"country": "xxxxx",
"stateCode": null
}
}
}
]
}
]
I am using The below extension method to get data for some other API's I have integrated in my system. This works fine for the other API's I have integrated.
public static string GetJsonField(RestSharp.IRestResponse value, string res)
{
Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(value.Content);
res = json.GetValue(res).ToString();
return res;
}
Thanks in advance
Copy that Json in json2csharp.com, it will give you the classes that you will need to convert the Json in a c# object.
Then just use var myJson = JsonConverter.deserialize(Json) ;
And you can access to the Json properties as you do with any other class

how to build a good c# data structure

my aim is to develop a custom search based on goeuro.com(overview) in my spare time.
I simplyfied the search parameters to the minimum.
For example(you can try this, as loong as the search_id is valid):
http://www.goeuro.com/GoEuroAPI/rest/api/v5/results?&search_id=428558909
The search_id will be generated when you visit http://www.goeuro.com and enter the first time your search parameters.
This is the simplified data structure I generated from http://json2csharp.com/ using this as my input JSON:
{
"serviceVersion": "v1.0.0",
"sortVariants": null,
"companies": {
"1007": {
"name": "Eurolines Germany",
"logoUrl": "http://cdn-goeuro.com/static_content/web/logos/{size}/eurolines_germany.png",
"id": "1007"
}
},
"outbounds": {
"3624107261930718525-38-flight-1-27": {
"companyId": "38",
"mode": "flight",
"duration": "873",
"outboundId": "3624107261930718525",
"journeyId": "27",
"departureTime": "2017-01-15T19:12:00.000+01:00",
"arrivalTime": "2017-01-16T09:45:00.000+01:00",
"stops": "1",
"price": 16209,
"updatedAt": "1",
"segments": [ 1344486303, 574447503, 689435565, 833161604 ],
"arrivalOvernightOffset": 1,
"overnightOffset": 1
}
},
"query": {
"roundTrip": false,
"airportToAirport": false,
"locationsOutsideEurope": false,
"searchId": "428558909",
"departurePosition": "377001",
"arrivalPosition": "398532",
"departureDate": "2017-01-15T00:00:00.000+01:00",
"passengers": {
"adults": 1,
"children": 0,
"infants": 0
},
"userInfo": {
"userLocale": "en",
"userCurrency": "EUR"
},
"searchModes": {
"bus": {
"status": "done",
"resultsQty": 13,
"filteredResultsQty": 13
},
"flight": {
"status": "done",
"resultsQty": 276,
"filteredResultsQty": 276
},
"train": {
"status": "done",
"resultsQty": 4,
"filteredResultsQty": 4
}
}
},
"itineraries": [
{ "outboundLegId": "3624107261930718525-38-flight-1-27" }
],
"segmentDetails": {
"1002857016": {
"type": "flight",
"departureTime": "2017-01-16T08:35:00.000+01:00",
"arrivalTime": "2017-01-16T12:05:00.000+02:00",
"departurePosition": "313870",
"arrivalPosition": "314920",
"duration": "150",
"company": "190",
"transportId": "ca6199",
"direction": "OUTBOUND",
"overnightOffset": 1,
"departureOvernightOffset": 1,
"arrivalOvernightOffset": 1
}
},
"positions": {
"2091737": {
"positionType": "busstation",
"name": "Warszawa, Warszawa Centralny",
"cityName": "Warsaw",
"latitude": 52.22782,
"longitude": 21.00224
}
},
"currencies": {
"EUR": {
"name": "Euro",
"symbol": "€"
}
}
}
The result from http://json2csharp.com/ is pretty good, but on the other side it generates something like this
public class Outbounds
{
public __invalid_type__362410726193071852538Flight127 __invalid_name__3624107261930718525-38-flight-1-27 { get; set; }
}
I see two problems here:
using __invalid_name__3624107261930718525-38-flight-1-27 is not a valid identifier in c#
and the above mentioned name is some random name, which I can not rely on my data structure.
So, my actually questions are:
How can I handle the request ?
How shall the data structure look like ?
By the way this is the code I am using(plus the generated results from http://json2csharp.com/):
static void Main()
{
var client = new RestClient("https://www.goeuro.com");
var request = new RestRequest("/GoEuroAPI/rest/api/v5/results?&search_id=428558909", Method.GET);
request.RequestFormat = DataFormat.Json;
// contentType: "application/json; charset=utf-8",
var response = client.Execute<Response>(request).Data;
}
Actually I found an existing solution(partly) for my problem:
https://github.com/evgenTraytyak/goeuro-api
, which is actually written in node.js, but I need c#, but by the way this example does not quite work(only if you have an existing search_id) and at the end I want to get the search_id from goeuro, without manually type it to my code.
Maybe the reason that using this is that the JSON-Format changed...

Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path

I am working on a Windows Phone 8.1 application involving location. I am receiving Json data from my API. My API returns data that looks like:
[{
"country": "India",
"city": "Mall Road, Gurgaon",
"area": "Haryana",
"PLZ": "122002",
"street": "",
"house_no": "",
"POI": "",
"type": "17",
"phone": "",
"lng": 77.08972334861755,
"lat": 28.47930118040612,
"formatted_address": "Mall Road, Gurgaon 122002, Haryana, India"
},
{
"country": "India",
"city": "Mall Road, Kanpur",
"area": "Uttar Pradesh",
"PLZ": "208004",
"street": "",
"house_no": "",
"POI": "",
"type": "17",
"phone": "",
"lng": 80.35783410072327,
"lat": 26.46026740300029,
"formatted_address": "Mall Road, Kanpur 208004, Uttar Pradesh, India"
},
{
"country": "India",
"city": "Mall Road Area, Amritsar",
"area": "Punjab",
"PLZ": "143001",
"street": "",
"house_no": "",
"POI": "",
"type": "17",
"phone": "",
"lng": 74.87286686897278,
"lat": 31.64115178002094,
"formatted_address": "Mall Road Area, Amritsar 143001, Punjab, India"
},
{
"country": "India",
"city": "Vasant Kunj (Mall Road Kishan Garh), New Delhi",
"area": "Delhi",
"PLZ": "110070",
"street": "",
"house_no": "",
"POI": "",
"type": "18",
"phone": "",
"lng": 77.1434211730957,
"lat": 28.51363217008815,
"formatted_address": "Vasant Kunj (Mall Road Kishan Garh), New Delhi 110070, Delhi, India"
}]
I am deserializing my Json data and putting it into a class named LocationData. When I run my code, it gives me an error:
Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path
Where am I going wrong? Here is my code:
private async void GetAPIData()
{
string _serviceUrl = "https://api.myweblinkapiprovider/v2&q=" + UserRequestedLocation;
HttpClient client = new HttpClient();
HttpResponseMessage responce = await client.GetAsync(new Uri(_serviceUrl));
if (responce.Content != null)
{
var respArray = JObject.Parse(await responce.Content.ReadAsStringAsync());
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.MissingMemberHandling = MissingMemberHandling.Ignore;
var rcvdData = JsonConvert.DeserializeObject<LocationData>(respArray.ToString(), settings);
UpdateMapData(rcvdData);
UpdateTextData(rcvdData);
}
}
I also tried to use a JArray. My code is as below:
private async void GetAPIData()
{
string _serviceUrl = "https://api.myweblinkprovider.com/v3?fun=geocode&lic_key=MyKey" + UserRequestedLocation;
HttpClient client = new HttpClient();
HttpResponseMessage responce = await client.GetAsync(new Uri(_serviceUrl));
JArray arr = JArray.Parse(await responce.Content.ReadAsStringAsync());
foreach (JObject obj in arr.Children<JObject>())
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.MissingMemberHandling = MissingMemberHandling.Ignore;
var rcvdData = JsonConvert.DeserializeObject<LocationData>(arr.ToString(), settings);
UpdateMapData(rcvdData);
UpdateTextData(rcvdData);
}
}
It also gives me an error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'MMI_SpeechRecog.Model.LocationData' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
The first part of your question is a duplicate of Why do I get a JsonReaderException with this code?, but the most relevant part from that (my) answer is this:
[A] JObject isn't the elementary base type of everything in JSON.net, but JToken is. So even though you could say,
object i = new int[0];
in C#, you can't say,
JObject i = JObject.Parse("[0, 0, 0]");
in JSON.net.
What you want is JArray.Parse, which will accept the array you're passing it (denoted by the opening [ in your API response). This is what the "StartArray" in the error message is telling you.
As for what happened when you used JArray, you're using arr instead of obj:
var rcvdData = JsonConvert.DeserializeObject<LocationData>(arr /* <-- Here */.ToString(), settings);
Swap that, and I believe it should work.
Although I'd be tempted to deserialize arr directly as an IEnumerable<LocationData>, which would save some code and effort of looping through the array. If you aren't going to use the parsed version separately, it's best to avoid it.
In this case that you know that you have all items in the first place on array you can parse the string to JArray and then parse the first item using JObject.Parse
var jsonArrayString = #"
[
{
""country"": ""India"",
""city"": ""Mall Road, Gurgaon"",
},
{
""country"": ""India"",
""city"": ""Mall Road, Kanpur"",
}
]";
JArray jsonArray = JArray.Parse(jsonArrayString);
dynamic data = JObject.Parse(jsonArray[0].ToString());
I ran into a very similar problem with my Xamarin Windows Phone 8.1 app. The reason JObject.Parse(json) would not work for me was because my Json had a beginning "[" and an ending "]". In order to make it work, I had to remove those two characters. From your example, it looks like you might have the same issue.
jsonResult = jsonResult.TrimStart(new char[] { '[' }).TrimEnd(new char[] { ']' });
I was then able to use the JObject.Parse(jsonResult) and everything worked.
The following worked for me to convert a list of objects to json.
using Newtonsoft.Json;
static void Main(string[] args)
{
List<eventResponse> o = new List<eventResponse>()
{
new eventResponse { acknowledge = "test" } ,
new eventResponse { acknowledge = "test 2" }
};
var json = JsonConvert.SerializeObject(o);
JArray jo = JArray.Parse(json);
Console.WriteLine(jo);
}
public class eventResponse
{
public string acknowledge { get; set; }
}
A delayed answer but if you have access to the API you can work on the javascript object to make it as JSon. Something like
var jsonAddresses = { "addresses":
[
{
"country": "India",
"city": "Mall Road, Gurgaon",
},
{
"country": "India",
"city": "Mall Road, Kanpur",
}
]};
Then in C#
JObject Addjson = JObject.Parse(model.YourAddressesSampleJSONStr);

Deserializing Chrome Bookmark JSON Data in C#

In response to a question I asked a few days ago, I'm attempting to stretch myself a little, and do something that I've not really focussed on much before. I've done some searching (both here, and in general), but can't find the answers (or even reasonable hints) to what I want to achieve (though, a few things come close-ish).
Basically, I'm trying to deserialize the data for the Google Chrome bookmarks file using the Json.NET library (though, if there's a better alternative, I'm all for that - the documentation for this library is a little confusing in places). I'm a little confused as to the next step to take, due primarily to being used to PHP's fantastic handling of JSON data (using json_decode()), allowing for a single function call, and then simple associative-array access.
The library (Json.NET) wants me to specify an Object type that it can deserialize the JSON data into, but I'm not really sure how to go about structuring such an Object, given the format of the Bookmarks file itself. The format is something along the lines of:
{
"roots": {
"bookmark_bar": {
"children": [ {
"children": [ {
"date_added": "12880758517186875",
"name": "Example URL",
"type": "url",
"url": "http://example.com"
}, {
"date_added": "12880290253039500",
"name": "Another URL",
"type": "url",
"url": "http://example.org"
} ],
"date_added": "12880772259603750",
"date_modified": "12880772452901500",
"name": "Sample Folder",
"type": "folder"
}, {
"date_added": "12880823826333250",
"name": "Json.NET",
"type": "url",
"url": "http://james.newtonking.com/pages/json-net.aspx";
} ],
"date_added": "0",
"date_modified": "12880823831234250",
"name": "Bookmarks bar",
"type": "folder"
},
"other": {
"children": [ ],
"date_added": "0",
"date_modified": "0",
"name": "Other bookmarks",
"type": "folder"
}
},
"version": 1
}
Now, in PHP, I'd be far more used to doing something along the lines of the following, to get the data I wanted, and ending up with 'Json.NET':
$data['roots']['bookmark_bar']['children'][0]['name'];
I can work out, simply enough, what objects to create to represent the data (something like a root object, then a bookmark list object, and finally an individual bookmark object) - but I'm really not sure as to how to implement them, and then get the library to deserialize into the relevant objects correctly.
Any advice that can be offered would be greatly appreciated.
It is not necessary to declare a type that reflects the json structure:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System;
class Program
{
static void Main(string[] args)
{
string json =
#"
{
""roots"": {
""bookmark_bar"": {
""children"": [ {
""children"": [ {
""date_added"": ""12880758517186875"",
""name"": ""Example URL"",
""type"": ""url"",
""url"": ""http://example.com""
}, {
""date_added"": ""12880290253039500"",
""name"": ""Another URL"",
""type"": ""url"",
""url"": ""http://example.org""
} ],
""date_added"": ""12880772259603750"",
""date_modified"": ""12880772452901500"",
""name"": ""Sample Folder"",
""type"": ""folder""
}, {
""date_added"": ""12880823826333250"",
""name"": ""Json.NET"",
""type"": ""url"",
""url"": ""http://james.newtonking.com/pages/json-net.aspx""
} ],
""date_added"": ""0"",
""date_modified"": ""12880823831234250"",
""name"": ""Bookmarks bar"",
""type"": ""folder""
},
""other"": {
""children"": [ ],
""date_added"": ""0"",
""date_modified"": ""0"",
""name"": ""Other bookmarks"",
""type"": ""folder""
}
},
""version"": 1
}
";
using (StringReader reader = new StringReader(json))
using (JsonReader jsonReader = new JsonTextReader(reader))
{
JsonSerializer serializer = new JsonSerializer();
var o = (JToken)serializer.Deserialize(jsonReader);
var date_added = o["roots"]["bookmark_bar"]["children"][0]["date_added"];
Console.WriteLine(date_added);
}
}

Categories

Resources