Deserialize certain nested properties into class - c#

I have a large json file and only want to use certain nested properties, here is the file
{
"type": "champion",
"format": "standAloneComplex",
"version": "6.24.1",
"data": {
"Aatrox": {
"version": "6.24.1",
"id": "Aatrox",
"key": "266",
"name": "Aatrox",
"title": "the Darkin Blade",
"blurb": "Aatrox is a legendary warrior, one of only five that remain of an ancient race known as
the Darkin. He wields his massive blade with grace and poise, slicing through legions in a style
that is hypnotic to behold. With each foe felled, Aatrox's ...",
"info": {
"attack": 8,
"defense": 4,
"magic": 3,
"difficulty": 4
},
"image": {
"full": "Aatrox.png",
"sprite": "champion0.png",
"group": "champion",
"x": 0,
"y": 0,
"w": 48,
"h": 48
},
"tags": [
"Fighter",
"Tank"
],
},
"Ahri": {
"version": "6.24.1",
"id": "Ahri",
"key": "103",
"name": "Ahri",
"title": "the Nine-Tailed Fox",
"blurb": "Unlike other foxes that roamed the woods of southern Ionia, Ahri had always felt a
strange connection to the magical world around her; a connection that was somehow incomplete.
Deep inside, she felt the skin she had been born into was an ill fit for ...",
"info": {
"attack": 3,
"defense": 4,
"magic": 8,
"difficulty": 5
},
"image": {
"full": "Ahri.png",
"sprite": "champion0.png",
"group": "champion",
"x": 48,
"y": 0,
"w": 48,
"h": 48
},
"tags": [
"Mage",
"Assassin"
],
},
It is a very long json file. I have a class that is
public class Champion
{
public string id { get; set; }
public string key { get; set; }
public string name { get; set; }
public string title { get; set;}
}
public class ChampionRoot
{
public Dictionary<string, Champion> champions { get; set; }
}
What I am trying to do is start at the properties inside "Data" and only get "id", "key","name" and "title", and Deserialize those properties into my ChampionRoot class. I have searched and tried many things and cannot get it to work. Here is some of what I've tried in my controller
public IActionResult Champions()
{
var url = #"url.......";
WebClient client = new WebClient();
var download = client.DownloadString(url);
var champions = Newtonsoft.Json.JsonConvert.DeserializeObject<ChampionRoot>(download);
return Json(champions); //This returns null in the view
}
I have also tried using JObject a few different ways and that doesn't work for me either
JObject obj = JObject.Parse(download);
var json = obj["key"]["id"]["name"]["title"]; //throws object reference error
Then I've tried this
JObject obj = JObject.Parse(download);
var champions = Newtonsoft.Json.JsonConvert.DeserializeObject<ChampionRoot>(obj.ToString());
//This also returns null in the view
I have searched and read many answers but I cannot figure it out. The question is how can I only Deserialize those 4 nested properties into an object? The url is http://ddragon.leagueoflegends.com/cdn/6.24.1/data/en_US/champion.json for full json file.

You can use Dictionary<string, Champion> for data property:
public class ChampionRoot
{
public Dictionary<string,Champion> data { get; set; }
}
var champions = Newtonsoft.Json.JsonConvert.DeserializeObject<ChampionRoot>(download);

Related

Create object of json when elements are variables

i need help for deserialize this json on C#.
{
"date": "2021-01-04T16:58:06-03:00",
"resultsInThisPage": 2,
"currentPage": 1,
"totalPages": 1,
"paymentOrders": {
"3AC525B8EF5F413D86CFDC9318E8B3F8": {
"code": "3AC525B8EF5F413D86CFDC9318E8B3F8",
"status": 5,
"amount": 3.00,
"grossAmount": 3,
"lastEventDate": "2021-01-04T16:54:36-03:00",
"schedulingDate": "2021-01-04T16:54:31-03:00",
"transactions": [
{
"code": "AF63C1B13EF14F318C51119CBE1E5CA4",
"date": "2021-01-04T16:54:32-03:00",
"status": 3
}
],
"discount": {
"type": "DISCOUNT_PERCENT",
"value": 0
}
},
"1E5A8F8D35D34938A12281BD45C62DBE": {
"code": "1E5A8F8D35D34938A12281BD45C62DBE",
"status": 1,
"amount": 3.00,
"grossAmount": 0,
"lastEventDate": "2021-01-04T16:54:33-03:00",
"schedulingDate": "2021-02-04T05:54:31-03:00",
"transactions": [],
"discount": {
"type": "DISCOUNT_PERCENT",
"value": 0
}
}
}
}
I´m trying use one Class for make this, but the elements of "paymentOrders" are variables.
How is the best way for do this?
I need create a object to manipulate these values.
paymentOrders would be a Dictionary<string,SomeObject> where SomeObject represents the object with all the properties like code, status etc
You can use Dictionary<string, SomeType> (or even Dictionary<Guid, SomeType> in your case, based on provided sample) to represent dynamic property names for paymentOrders json object. Something like this should do the trick:
public class Root {
// your dynamic prop
public Dictionary<string, PaymentOrder> paymentOrders { get; set; }
public DateTime date { get; set; }
// ... the rest o properties
}
public class PaymentOrder {
public string code { get; set; }
public int status { get; set; }
// ... the rest o properties
}

How do I deserialize a tree of objects into a DTO?

I am attempting to deserialize a tree of JSon objects I get back into a DTO. The tree can be up to 4 levels deep, and over 1200 nodes. The code is C# using Newtonsoft.Json for deserialization.
EDIT
The JSon looks like:
[
{
"id": 1095,
"name": "Item1-1",
"children": [
{
"id": 1097,
"name": "Item2-2",
"children": [
{
"id": 18,
"name": "Item3-3",
"children": [
{
"id": 19,
"name": "Item4-4",
"children": [],
"level": 4,
"parentId": 18
},
{
"id": 20,
"name": "Item5-4",
"children": [],
"level": 4,
"parentId": 18
}
],
"level": 3,
"parentId": 1097
}
],
"level": 2,
"parentId": 1095
}
],
"level": 1,
"parentId": null
}
]
My DTO is similar to this:
public class MyDTO
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("children")]
public MyDTO[] Children { get; set; }
[JsonProperty("level")]
public int Level { get; set; }
[JsonProperty("parentId")]
public int ParentId { get; set; }
public MyDTO()
{
}
}
I like Brian Rogers' solution in this link, which deserializes the json into objects:
How do I use JSON.NET to deserialize into nested/recursive Dictionary and List?
public static class JsonHelper
{
public static object Deserialize(string json)
{
return ToObject(JToken.Parse(json));
}
private static object ToObject(JToken token)
{
switch (token.Type)
{
case JTokenType.Object:
return token.Children<JProperty>()
.ToDictionary(prop => prop.Name,
prop => ToObject(prop.Value));
case JTokenType.Array:
return token.Select(ToObject).ToList();
default:
return ((JValue)token).Value;
}
}
}
I call the JSonHelper with object obj = JsonHelper.Deserialize(jsonString);
I have been experimenting with converting this code into a method to convert to MyDTO, but I keep running into compiler errors. I have attempted to simply convert the JValue casts with MyDTO and move on to the List with a List.
My goal is to call MyDTO obj = JsonHelp.Deserialize(jsonString) and get the tree of MyDTO objects back. Is it possible to do what I am trying, or should I find a way to cast each object to MyDTO?
First your JSON is missing a brakcet ], then your model needs a nullable parentId. Making a couple simple changes you can then you JsonConvert.DeserializeObject<IEnumerable<MyDTO>>(json).
So your JSON should look like this:
[
{
"id": 1095,
"name": "Item1-1",
"children": [
{
"id": 1097,
"name": "Item2-2",
"children": [
{
"id": 18,
"name": "Item3-3",
"children": [
{
"id": 19,
"name": "Item4-4",
"children": [],
"level": 4,
"parentId": 18
},
{
"id": 20,
"name": "Item5-4",
"children": [],
"level": 4,
"parentId": 18
}
],
"level": 2,
"parentId": 1095
}],
}],
"level": 1,
"parentId": null
}
]
And can be deserialized with this model:
public class MyDTO
{
public int Id { get; set; }
public string Name { get; set; }
public MyDTO[] Children { get; set; }
public int Level { get; set; }
public int? ParentId { get; set; }
}
Using this code:
var dto = JsonConvert.DeserializeObject<IEnumerable<MyDTO>>(json);

reading HttpwebResponse in json format

I have doubt about how creating a class for receiving the response from HttpWebResponse.
The code I use for receiving a json response is:
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
JavaScriptSerializer js = new JavaScriptSerializer();
var objText = reader.ReadToEnd();
ResJson myojb = (ResJson )js.Deserialize(objText, typeof(ResJson ));
}
}
The json I receive is:
{
"name": "Rube Goldberg Machine Stage 1",
"published": true,
"description": "<p>.STEP Version\n<br /><br>Rube Goldberg Experiment</p>",
"raw_description": ".STEP Version\r\nhttp://grabcad.com/cadfiles/rube-goldberg-experiment",
"cached_slug": "rube-goldberg-machine-stage-1",
"created_at": "2011-04-06T21:58:06Z",
"updated_at": "2017-05-02T07:44:08Z",
"preview_image": "https://d2t1xqejof9utc.cloudfront.net/screenshots/pics/08d3763d43243a1a5f88c89dbfb8910c/card.jpg",
"image_missing_url": "https://d2t1xqejof9utc.cloudfront.net/screenshots/pics/missing_small.png",
"likes_count": 9,
"downloads_count": 116,
"comments_count": 1,
"contentfiles_count": 3,
"top_comments_count": 1,
"video_link": "https://youtu.be/paDE3KO7eb0",
"author": {
"name": "Scott Bruins",
"cached_slug": "scott.bruins",
"avatar": "https://d2t1xqejof9utc.cloudfront.net/members/avatars/320/feed.gif?1316795450"
},
"tags": [
"machine",
"rube",
"goldberg",
"crowdcad"
],
"softwares": [
{
"name": "Other",
"cached_slug": "other"
},
{
"name": "STL",
"cached_slug": "stl"
},
{
"name": "Rendering",
"cached_slug": "rendering"
}
]
}
When creating the ResJson class I can not figure out how set softwares variable type.
How should it be declared?
public class Software
{
[JsonProperty("name")]
public string Name {get;set;}
[JsonProperty("cached_slug")]
public string CachedSlug {get;set;}
}
And then in your ResJson:
{
...
[JsonProperty("softwares")]
public List<Software> Softwares {get;set;}
...
}

jsonResult with collectionname

Hi I would like to use the json collection from the code below in an angular repeater.
I need to give the collection a name but i dont know how
this is the code to generate the JSON
public JsonResult GetProducts()
{
var result = db.Products.ToList();
var list = JsonConvert.SerializeObject(result, Formatting.None, new JsonSerializerSettings(){ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore});
return Json(list,JsonRequestBehavior.AllowGet);
}
and this is the result
[{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 10006,
"Description": "TEST",
"Name": "TEST",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-11T14:52:57.677"
},
{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 20005,
"Description": "TEST2",
"Name": "TEST2",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-12T12:02:10.593"
}]
and I would like it to be like the code below so I can use the products tag to iterate .
{
"products": [{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 10006,
"Description": "TEST",
"Name": "TEST",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-11T14:52:57.677"
},
{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 20005,
"Description": "TEST2",
"Name": "TEST2",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-12T12:02:10.593"
}]}
If you are using WebAPI controllers you don't need to send JsonResult, all you need to do is create a class and send it back to client:
public class MyClass
{
public List<Product> Products { get; set; }
}
And in your controller:
public MyClass Get() {
return new MyClass {
Products = db.Products.ToList()
};
}
OR:
Simply create your object and then pass it in the serializer:
JsonConvert.SerializeObject( { "products": result }, Formatting.None, new JsonSerializerSettings(){ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore})
You can use
var list = JsonConvert.SerializeObject(new { products = result }, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore });
One solution for your problem is, define a seperate class and define a property for that class as either a collection or list of the type "db.Products"(Use the appropriate class name for this object as you have in your code) and when you serialize that object you will get it as you have asked for
class ProductList
{
public Collection<YourType> Products{get; set;}
}
OR
class ProductList
{
public List<YourType> Products{get; set;}
}

Cannot deserialize the current JSON array

First: I'm new to using JSON, and I used the answers on here to use Json.Net to deserialize data from a Pokemon API into a C# class (Pokemon class). I used http://json2csharp.com to help me define my class and it looks like this:
public class Pokemon
{
public Pokemon(string json)
{
JsonConvert.PopulateObject(json, this, PokeApi.JsonSerializerSettings);
}
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("evolutions")]
public Evolutions evolutions { get; set; }
[JsonProperty("national_id")]
public int national_id { get; set; }
}
with a bunch of other properties like resource_uri, attack stat, etc.
As the answer offered on the aforementioned link said, I used JsonConvert.DeserializeObject(json) like so:
public Pokemon GetPokemon(int nationalId)
{
using (WebClient client = new WebClient())
{
var json = client.DownloadString("http://pokeapi.co/api/v1/pokemon/" + nationalId + "/");
var output = JsonConvert.DeserializeObject<Pokemon>(json);
return output;
}
}
However I keep getting an exception that says "Cannot deserialize the current JSON array (e.g.[1,2,3]) into type 'Evolutions' because the type requires a JSON object..."
I found a lot of other questions asking the same exact thing, but I was confused with the top answers - sometimes the answer was to use JsonProperty, sometimes it was to use JsonConverter, without really an explanation on what all these meant. Do I need both?
Edit: sample json (call: http://pokeapi.co/api/v1/pokemon/1/)
{
"abilities": [
{
"name": "overgrow",
"resource_uri": "/api/v1/ability/1/"
},
{
"name": "chlorophyll",
"resource_uri": "/api/v1/ability/2/"
}
],
"attack": 49,
"catch_rate": 45,
"created": "2013-11-02T12:08:25.745455",
"defense": 49,
"egg_cycles": 21,
"egg_groups": [
{
"name": "Monster",
"resource_uri": "/api/v1/egg/1/"
},
{
"name": "Grass",
"resource_uri": "/api/v1/egg/8/"
}
],
"ev_yield": "1 Sp Atk",
"evolutions": {
"level": 16,
"method": "level up",
"resource_uri": "/api/v1/pokemon/2/",
"to": "Ivysaur"
},
"exp": 64,
"growth_rate": "ms",
"happiness": 70,
"height": "2'4",
"hp": 45,
"male_female_ratio": "87.5/12.5",
"modified": "2013-11-02T13:28:04.914889",
"moves": [
{
"learn_type": "other",
"name": "Tackle",
"resource_uri": "/api/v1/move/1/"
},
{
"learn_type": "other",
"name": "Growl",
"resource_uri": "/api/v1/move/2/"
},
{
"learn_type": "level up",
"level": 10,
"name": "Vine whip",
"resource_uri": "/api/v1/move/3/"
}
],
"name": "Bulbasaur",
"national_id": 1,
"resource_uri": "/api/v1/pokemon/4/",
"sp_atk": 65,
"sp_def": 65,
"species": "seed pokemon",
"speed": 45,
"total": 318,
"types": [
{
"name": "grass",
"resource_uri": "/api/v1/type/5/"
},
{
"name": "poison",
"resource_uri": "/api/v1/type/8/"
}
],
"weight": "15.2lbs"
}
Evolutions class:
public class Evolutions
{
public int level { get; set; }
public string method { get; set; }
public string resource_uri { get; set; }
public string to { get; set; }
}
I tried http://json2csharp.com/ with http://pokeapi.co/api/v1/pokemon/19/ and what I see is
public class RootObject
{
//...
public List<Evolution> evolutions { get; set; }
//...
}
This pretty mush is your Pokemon class. So you need to declare Evolutions as list.

Categories