C# get children from JSON - c#

my JSON looks like this:
{
"kind": "youtube#videoListResponse",
"etag": "\"sZ5p5Mo8dPpfIzLYQBF8QIQJym0/TOPzMxlQJUtRJBXHeKYMXsdEkHs\"",
"pageInfo":
{
"totalResults": 1,
"resultsPerPage": 1
},
"items":
[
{
"kind": "youtube#video",
"etag": "\"sZ5p5Mo8dPpfIzLYQBF8QIQJym0/BIVqr1Mkbule8othzWvZRor92wU\"",
"id": "QMNkWwq6L4Q",
"contentDetails":
{
"duration": "PT4M45S",
"dimension": "2d",
"definition": "hd",
"caption": "false",
"licensedContent": true,
"projection": "rectangular"
}
}
]
}
The formatting might be a bit off, sorry.
I tried creating a class like this:
public class VideoDetails
{
public string kind;
public string etag;
public string id;
public string duration;
public string definition;
public string caption;
public string licensedContent;
public string projection;
}
After that I deserialize the JSON file:
VideoDetailRead = JsonConvert.DeserializeObject<VideoDetails>(json);
but I only get "etag" and "kind". Nothing else. My question is: How do I read the data that's listed under "items"? This is my first time working with JSON and therefor I don't know much. Thanks for some answers.

Create a second object to model the children data. Provided the items property has also a child under contentDetails, you will also need another object to deserialize these properties.
public class VideoDetailsItem
{
public string kind;
public string etag;
public string id;
public VideoContentDetails contentDetails;
}
public class VideoContentDetails
{
public string duration;
public string definition;
public string caption;
public bool licensedContent;
public string projection;
}
And to the parent object add a List<VideoDetailsItem>.
public class VideoDetails
{
public string kind;
public string etag;
public List<VideoDetailsItem> items;
}
When deserializing JSON objects you have to mimic the JSON object structure in your object. Also, consider using properties instead of public fields to favor encapsulation in your data objects.

The properties you have listed are inside an array named items, so your object hierarchy has to match this:
public class VideoList
{
public string kind;
public string etag;
// etc...
public List<VideoDetails> items;
}
public class VideoDetails
{
public string kind;
public string etag;
public string id;
public string duration;
public string definition;
public string caption;
public string licensedContent;
public string projection;
}
Then:
var videos = JsonConvert.DeserializeObject<VideoList>(json);

This is because you aren't properly modeling the object structure. Right now, your JSON is structured like:
{baseInformation, VideoDetailsArray}
Thus you have to restructure your data object as
public class VideoDetails
{
//Base information
public string kind {get; set;}
public string etag {get; set;}
//...
public List<VideoDetails> {get; set;}
}

You have to define your class to match the structure of the JSON: in this case, you would define items as a list of a separate class which has the properties under it like duration etc. You should have your VideoDetails class nested inside another class that can wrap both objects in the JSON, and add another class for the contentDetails object.
One thing you can do is copy the JSON into your clipboard, open a new class file in Visual Studio, and go to Edit > Paste Special > Paste JSON as Classes. This will create the correct structure for you, and you can see how the nested classes in the JSON properly translate to C# classes.

Related

REST API Deserialize Nested Response in Newtonsoft.Json

EDIT: Once I have this information deserialized, how can I access the data I need? The only information I need to grab is the TransitTime and the Cost for each accessorial.
I'm working with an API in which I need data from nested objects, but I'm unsure of how to access this information. I've passed my data to the API and have set up new classes based on how the data comes back from the API.
Here's what the response looks like:
{"RatingResponse":
{"Success":"true",
"Message":"",
"QuoteID":"57450",
"LoadNum":"57450",
"Rates":{
"Rate":[
{"SCAC":"TEST",
"CarrierName":"TEST",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"983.69",
"ThirdPartyCharge":"983.69",
"Accessorials":{
"Accessorial":[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-985.55",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"313.69",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
},
{"SCAC":"TEST2",
"CarrierName":"TEST2",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"983.69",
"ThirdPartyCharge":"983.69",
"Accessorials":{
"Accessorial":[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-985.55",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"313.69",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
}
]
},
"AverageTotalCost":"983.69"
}
}
I've converted it to C#:
public class Accessorial
{
public string Code;
public string Cost;
public string Description;
}
public class Accessorials
{
public List<Accessorial> Accessorial;
}
public class Rate
{
public string SCAC;
public string CarrierName;
public string TransitTime;
public string ServiceLevel;
public string TotalCost;
public string ThirdPartyCharge;
public Accessorials Accessorials;
public string QuoteNumber;
}
public class Rates
{
public List<Rate> Rate;
}
public class RatingResponse
{
public string Success;
public string Message;
public string QuoteID;
public string LoadNum;
public Rates Rates;
public string AverageTotalCost;
}
public class Root
{
public RatingResponse RatingResponse;
}
The only values I need are the Rate Transit Time and Service Level as well as the Accessorial Costs. I'm a beginner with APIs and am not sure how to return only that information. Any help is greatly appreciated!
you don't need any classes if you use this code
var rate = (JArray)JObject.Parse(json)["RatingResponse"]["Rates"]["Rate"];
var result = rate.Select(r => new
{
TransitTime = (int)r["TransitTime"],
ServiceLevel = (string) r["ServiceLevel"],
AccessorialCost = ((JArray)r["Accessorials"]["Accessorial"]).Select(r => (double)r["Cost"]).ToList()
});
result (in json format)
[
{
"TransitTime": 1,
"ServiceLevel": "D",
"AccessorialCost": [
1655.55,
-985.55,
313.69
]
},
{
"TransitTime": 1,
"ServiceLevel": "D",
"AccessorialCost": [
1655.55,
-985.55,
313.69
]
}
]
or you can create a Data class instead of an anonymous
List<Data> result = rate.Select(r => new Data
{
....
}).ToList();
public class Data
{
public int TransitTime { get; set; }
public string ServiceLevel { get; set; }
public List<double> AccessorialCost { get; set; }
}
I like #Serge's answer but I prefer to have results in a class because "I only need..." never holds for very long, right? Here is a good discussion of loading the JSON into a complex object:
Your JSON erred in JSON2C#.com but essentially your root object needs the other classes. Something like
public class Root
{
public RatingResponse RatingResponse;
public Rates Rates;
public Accessorials Accessorials;
}
and then deserialize into your complex object
JsonConvert.DeserializeObject<RootObject>(json)
I'm doing this off the top of my head so forgive any syntax errors.

JsonConvert Class which is inheritance with a list

I am using the code below for populating a list
public class Group : List<Body>
{
public string Title { get; set; }
public Group(string title)
{
Title = title;
}
}
public class Body
{
public string Name { get; set; }
}
private void Button_Clicked(object sender, EventArgs e)
{
var items = new List<Group> {
new Group("Title")
{
new Body { Name = "Dimitris" } }
};
var jsonstring = JsonConvert.SerializeObject(items);
}
My result is
[[{"Name":"Dimitris"}]]
It doesnt get the title property. Is there any way which i can fix this?
Sadly not every object can be serialized into valid json. And as I said in the comments what you want (something that has both a title property but is also a list) cannot be presented in valid json (in json something can have properties {} or something can be a list [] but not both), there are more structures that cannot be represented in valid json (circular dependencies for example) but sadly this is one of them.
Now I understand the need to inherit List<Group> for the ListView so this poses a problem. However this is not a problem that can't be worked around.
You need to separate the json from the models you bind to your views (this is in general a good practice imo). So you create an object that carries the data and can be serialized into valid json:
public class BodyGroupDto
{
public string Title;
public List<Body> Items;
}
This can now be represented by the following json:
[{
"Title": "SomeTitle",
"Items": [{
"Name": "Dimitris"
}]
}]
Now that we have the ability to send the data with json we still need to be able to convert our data object to the actual Group object we want to use in the view.
One way to do this is to add another constructor to the Group class so we can pass it both a title and items:
public class Group : List<Body>
{
public string Title { get; set; }
public Group(string title)
{
Title = title;
}
public Group(string title, IEnumerable<Body> items) : base(items)
{
Title = title;
}
}
And now we can convert this inside the Xamarin Forms application, for example that could look like this:
public List<Group> GetGroups(string json)
{
var bodyGroupList = JsonConvert.DeserializeObject<List<BodyGroupDto>>(json);
return bodyGroupList.Select(bodyGroup => new Group(bodyGroup.Title, bodyGroup.Items)).ToList();
}
And if you ever need to convert the other way around you could do something like this:
public string GetBodyGroupDtoListJson(List<Group> groups)
{
var bodyGroupList = groups.Select(group => new BodyGroupDto
{
Title = group.Title,
Items = group.ToList()
}).ToList();
return JsonConvert.SerializeObject(bodyGroupList);
}
Hope this helps and good luck with your project

Send a post request in JSON format

Below is the format of post request expected in JSON. Can anyone please tell me how to achieve this.
{
"MywebServiceInputDetail":{
"MyDatalst":{
"MyData":[
{
"name":"TestName",
"id":"2611201",
"SomeRefVal":"REF123456"
}
]
}
}
}
I am using JavaScriptSerializer as of now.
Below is the code.
[Serializable]
public struct MyStruct
{
public string name;
public string id;
public string refno;
}
JavaScriptSerializer jss = new JavaScriptSerializer();
string serializedJson = jss.Serialize(ObjMystrcut);
Above code results in the JSON string as
{"name":"TestName","id":"1234567","refno":"567123"}
I am new to JSON so I'm not able to formulate the request format.
I am avoiding to achieve it by hardcoding a json string. Basically, I am trying to understand what does { and [ bracketing mean. Does [ mean that I need to create an array of objects?
You can do something like this:
string serializedJson = jss.Serialize(new { MywebServiceInputDetail = new { MyDatalst = new { MyData = new[] { ObjMystrcut } } } });
{} is object notation, so it represents an object, with properties.
[] is an array notation.
Yes, the [ and ] symbols represent JSON arrays (collections of objects). In your example, MyData is a collection of those structs you created.
You need to create the following classes:
public class MywebServiceInputDetail
{
public MyDatalst MyDatalst { get; set; }
}
public class MyDatalst
{
public List<MyStruct> MyData { get; set; }
}
public struct MyStruct
{
public string name;
public string id;
public string SomeRefVal;
}
Now create a MywebServiceInputDetail object and serialize it.
Personally I would forget about using a struct and just create the following class instead:
public class MyClass
{
public string Name { get; set; }
public string Id { get; set; }
public string SomeRefVal { get; set; }
}
You should also add JSON attributes to the properties to make sure Name and Id are serialized with lowercase letters.

Deserialize varying JSONs to type hierarchy in ASP.NET Core

In my ASP.NET 2.0 WebApi I do receive slighty different types of JSONs as POST body. The JSONs I may receive look like this
{
"Version": "some string",
"Session": "somestring",
"Payload": {}
}
Payload then is one of these 3 variants:
{
"tmestamp": "string"
}
or this:
{
"tmestamp": "string",
"name": "string"
}
or this:
{
"tmestamp": "string",
"status": number,
"values": [
number,
number,
...
]
}
To have matching types I have created this hierarchy:
public class BaseRequest
{
public string Version {get;set;}
public string Session {get;set;}
public BasePayload Playload {get;set;}
}
public class BasePayload
{
public DateTime timestamp {get;set;}
}
public class PayloadVariant1 : BasePayload
{
public string Name {get;set;}
}
public class PayloadVariant2 : BasePayload
{
public int Status {get;set;}
public double[] Values {get;set}
}
The JSON format is defined by a third party vendor, so cannot be adjusted. I have defined my POST method as follows to get data:
[HttpPost]
public void Post([FromBody]BaseRequest content)
but Payload is always BasePayload and cannot be cast to a different type although the received data contains that content. Therefore I thought I may have to use Generics and define several posts:
// converted into a generic variant
public class BaseRequest<T> where T : BasePayload
{
public string Version {get;set;}
public string Session {get;set;}
public T Playload {get;set;}
}
[HttpPost]
public void Post([FromBody]BaseRequest<BasePayload> content)
[HttpPost]
public void Post([FromBody]BaseRequest<PayloadVariant1> content)
But then I get this exception Microsoft.AspNetCore.Mvc.Internal.ActionSelector:Error: Request matched multiple actions resulting in ambiguity. Matching actions: SkillMediator.Controllers.MessagesController.Post (SkillMediator). I found that the Newtonsoft.JSON can be configured to read a variable $type from the JSON which contains the fully qualified name of the type as a hint for deserialization. But as already said the JSONs come from a public API which I cannot change.
Is there a way to have, based on the given JSON format, fully type-safe data structures in my ASP.NET Core code?
You can merge all the variances into one model class:
public class BasePayload
{
public DateTime? timestamp {get;set;}
public string Name {get;set;}
public int? Status {get;set;}
public double[] Values {get;set}
}
But notice that I have used nullable types, so that properties not matched from the json will be left as null.

How to parse my Json Response String in C# [duplicate]

This question already has answers here:
Parse Json string in C#
(5 answers)
Closed 6 years ago.
This is the JSON Response I'm getting,I unable to parse,Please help me.
{
"features": [{
"attributes": {
"OBJECTID": 1,
"schcd": "29030300431",
"schnm": "UNAIDED GENITALIA LIPS DALMATIA RS"
},
"geometry": {
"x": 8449476.63052563,
"y": 1845072.4204768054
}
}]
}
To parse a JSON you will most likely need a extern library like JSON.Net or something similar.
Then you need to create a classes (a wrapper) with properties that match your JSON String and deserialize the string into that object.
When you create the wrapper class into which you want to deserialize your JSON String you have be careful to name the properties the same way they are named in the JSON String.
Example:
public class MyObject {
public List <Feature> Features {get;set;}
}
public class Feature {
public MyAttributes Attributes {get;set; }
public Geometries Geometries {get;set; }
}
public class MyAttributes {
public int ObjectID {get;set;}
public string Schcd {get;set;}
public string Schnm {get;set;}
}
public class Geometries {
public double X {get;set;}
public double Y {get;set;}
}
Then just call the deserialisation function of the JSON library:
var myObject = JsonConvert.DeserializeObject<MyObject>(jsonString);
To access a property like the Object ID then you just call:
myObject.Features[0].Attributes.ObjectId;
If you're ok with using dynamic you can do like this
var json = "{ \"features\" : [ { \"attributes\": { \"OBJECTID\": 1, \"schcd\": \"29030300431\", \"schnm\": \"UNAIDED GENITALIA LIPS DALMATIA RS\" }, \"geometry\": { \"x\": 8449476.63052563, \"y\": 1845072.4204768054 } } ] }";
dynamic obj = JsonConvert.DeserializeObject(json);
var objectId = obj.features[0].attributes.OBJECTID;
It uses Newtonsoft.Json, which can be installed with Nuget from here.
Install-Package Newtonsoft.Json
Be aware that this doesn't do any null-checks, and simply assumes that it's the first object in features that you want. But it's simple and doesn't require you to create any models.
If you want to use a more complete model I would go for the answer provided by Bojan B or j0ey_wh.
Here is an answer that might get you started Deserialize JSON with C#
I like more the solution from NewtonSoft: Newtonsoft JSON Deserialize
You can use their JsonConverter to simply serialize/deserialize objects
Here's a simple example:
You first need classes that match the structure of your JSON:
public class MyCoolClass
{
public IEnumerable<Feature> features {get; set;}
}
public class Feature
{
public Attributes Attributes {get; set;}
public Geometry Geometry {get; set;}
}
public class Attributes
{
public int ObjectId {get; set;}
public string Schcd {get; set;}
public string Schnm {get; set;}
}
public class Geometry
{
public double X {get; set;}
public double Y {get; set;}
}
Then you just use JsonConverter (JSON.Net) like this:
MyCoolClass tmp = JsonConvert.DeserializeObject<MyCoolClass>(jsonStringThatYouGot);

Categories