I usually use json2csharp to generate json classes to c#. But I do have problem. My json is have dynamic depth like this
{
"kategori": [
{
"id": "1",
"namakategori": "Tips & Trick",
"parent_id": "0",
"children": [
{
"id": "348",
"namakategori": "Fotografi",
"parent_id": "1",
"children": []
},
{
"id": "370",
"namakategori": "Hacking",
"parent_id": "1",
"children": []
}
]
},
{
"id": "12",
"namakategori": "Aplikasi",
"parent_id": "0",
"children": [
{
"id": "13",
"namakategori": "Tools",
"parent_id": "12",
"children": [
{
"id": "14",
"namakategori": "Toolsorder",
"parent_id": "13",
"children":[]
},
]
},
]
},
]
}
So how do I generate json classes dynamically so it can be used for my json? In above example I have 3 depth. But if I go to different page maybe it have 4 or more depth.
You don't need to declere your classes dynamically. This should work:
public class Child
{
public string id { get; set; }
public string namakategori { get; set; }
public string parent_id { get; set; }
public List<Child> children { get; set; } // <-- See this
}
public class RootObj
{
public List<Child> kategori { set; get; }
}
To deserialize I'll use Json.Net
var res = JsonConvert.DeserializeObject<RootObj>(json);
You can always use the Newtonsoft.Json
For Instance,
JObject result = (JObject) JsonConvert.DeserializeObject(yourJsonDataHere);
var katObject = result.Property("kategori").Value;
and so on...
PS: Not sure if Newtonsoft.Json is supported on WP7.
Related
Does Newtonsoft Json have any way to serialize nested objects with only selected properties ?
The model looks like:
class Node
{
int id{ get; set; };
string name{ get; set; };
IList<Node>children{ get; set; };
}
I am creating a tree structure afterwards which looks something like this:
{
"id": 1,
"name": "A",
"children": [
{
"id": 2,
"name": "B",
"children": null
},
{
"id": 3,
"name": "C",
"children": [
{
"id": 10,
"name": "D",
"children": null
}
]
}
]
}
Wrote my own serializer. I passed Children property only .It shows as:
{
"children": [
{
"children": null
},
{
"children": [
{
"children": null
}
]
}
]
}
I want to show all properties and not just children under 1st/root's children.Similar to below.
{
"children": [
{
"id": 2,
"name": "B",
"children": null
},
{
"id": 3,
"name": "C",
"children": [
{
"id": 10,
"name": "D",
"children": null
}
]
}
] }
Also how do I do the same for children.Id where I want to serialize all children.Id of root node,Similar to below
{
"children": [
{
"id": 2
},
{
"id": 3
}
]
}
they have done the same result you want to achieve on this page.
https://weblog.west-wind.com/posts/2012/aug/30/using-jsonnet-for-dynamic-json-parsing
Also, see Here,
https://entityframeworkcore.com/knowledge-base/58283745/self-reference-when-serializing-nested-object
I hope that will be useful.
What do you need your own serializer for? Try the standard one
var jsonDeserialized = JsonConvert.DeserializeObject<Child>(json);
json = JsonConvert.SerializeObject(jsonDeserialized);
Output
{
"id": 1,
"name": "A",
"children": [
{
"id": 2,
"name": "B",
"children": null
},
{
"id": 3,
"name": "C",
"children": [
{
"id": 10,
"name": "D",
"children": null
}
]
}
]
}
Classes
public partial class Child
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("children")]
public List<Child> Children { get; set; }
}
For this
{
"children": [
{
"id": 2,
"name": "B",
"children": null
},
{
"id": 3,
"name": "C",
"children": [
{
"id": 10,
"name": "D",
"children": null
}
]
}
] }
You can use
var jsonDeserialized = JsonConvert.DeserializeObject<Data>(json);
public partial class Data
{
[JsonProperty("children")]
public List<Child> Children { get; set; }
}
I have an array like this coming from API response and I want to filter by nested property products to returns product with only id 11
"assets": [
{
"name": "abc",
"products": [
{
"id": "11",
"status": true
},
{
"id": "14",
"status": null
}
]
},
{
"name": "xyz",
"products": [
{
"id": "11",
"status": true
},
{
"id": "28",
"status": null
}
]
},
{
"name": "123",
"products": [
{
"id": "48",
"status": null
}
]
},
{
"name": "456",
"products": [
{
"id": "11",
"status": true
}
]
}
]
the resulting output should look like this,
"assets": [
{
"name": "abc",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "xyz",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "123",
"products": []
},
{
"name": "456",
"products": [
{
"id": "11",
"status": true
}
]
}
]
I'm trying to return filter output with the C# LINQ method. but, getting an error when filtering a nested array with the following method
"Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type"
assets.Select(asset => asset.products.Where(product => product.id == "11")).ToArray();
You can just remove all items from every products array, whose id doesn't equal 11. Parse JSON to JObject, iterate over assets array, find products with id different from 11 and remove them form original array
var json = JObject.Parse(jsonString);
foreach (var asset in json["assets"])
{
var productsArray = asset["products"] as JArray;
if (productsArray == null)
continue;
var productsToRemove = productsArray
.Where(o => o?["id"]?.Value<int>() != 11)
.ToList();
foreach (var product in productsToRemove)
productsArray.Remove(product);
}
Console.WriteLine(json);
Instead of Select and Applying a, Where try to remove the Products that you do not want.
Following is a sample code.
class Program
{
static void Main(string[] args)
{
var json = #"
{
'assets': [
{
'name': 'abc',
'products': [
{
'id': '11',
'status': true
},
{
'id': '14',
'status': null
}
]
},
{
'name': 'xyz',
'products': [
{
'id': '11',
'status': true
},
{
'id': '28',
'status': null
}
]
},
{
'name': '123',
'products': [
{
'id': '48',
'status': null
}
]
},
{
'name': '456',
'products': [
{
'id': '11',
'status': true
}
]
}
]}";
var root = JsonConvert.DeserializeObject<Root>(json);
var assets = root.Assets;
assets.ForEach(a =>
{
a.Products.RemoveAll(p => p.Id != 11);
});
}
}
public partial class Root
{
[JsonProperty("assets")]
public List<Asset> Assets { get; set; }
}
public partial class Asset
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("products")]
public List<Product> Products { get; set; }
}
public partial class Product
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("status")]
public bool? Status { get; set; }
}
To filter the list, you will need to create a new list with products whose ID == YourId. Following linq query does the necessary steps to create the list you want.
Filter out any assets that dont have any product with ID == 11. This is necessary to skip nulls in the new list that will be generated (Where statement)
Create a collection / list of new assets that only have the products whose ID == 11 (Select statement)
var list = assets.Where(x => x.Products.Where(y => y.Id.Equals("11")).Count() > 0)
.Select(asset => {
return new Asset() {
Name = asset.Name,
Products = asset.Products.Where(x => x.Id == "11").ToList()
};
}).ToList();
// Create the RootObject that holds a list of all the arrays if you want.
Rootobject newAssetCollection = new Rootobject() { Assets = list };
Below is the Json that was printed
Console.WriteLine(JsonConvert.SerializeObject(newAssetCollection, Formatting.Indented));
{
"assets": [
{
"name": "abc",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "xyz",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "456",
"products": [
{
"id": "11",
"status": true
}
]
}
]
}
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);
I'm wondering if someone can elucidate a method to sort a list of objects based on a child object's attribute.
I'm working with the following model:
public class Content
{
public string Id { get; set; }
public List<ContentAttribute> Attributes { get; set; }
}
public class ContentAttribute
{
public string Value { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
Some sample data:
[
{
"Id": "123",
"Attributes": [
{
"Value": "abc",
"Id": "1a",
"Name": "name1"
},
{
"Value": "ghi",
"Id": "2b",
"Name": "name2"
}
]
},
{
"Id": "456",
"Attributes": [
{
"Value": "abc",
"Id": "1a",
"Name": "name2"
},
{
"Value": "def",
"Id": "2b",
"Name": "name3"
}
]
},
{
"Id": "789",
"Attributes": [
{
"Value": "abc",
"Id": "1a",
"Name": "name1"
},
{
"Value": "def",
"Id": "2b",
"Name": "name2"
}
]
}
]
How can I sort the Content objects by the Value of a specific attribute Name? For example, I would like to sort the above data by the Value of 'name2',
meaning the result would be
[
{"Id" : "456"},
{"Id" : "789"},
{"Id" : "123"}
]
Any help is greatly appreciated. (Using c#).
If Attributes always has an element with name name2 and you want an exception if it doesn't then:
var sorted = contents.OrderBy(c => c.Attributes.First(a => a.Name == "name2").Value).ToList();
Or if name2 could be missing and it's not deal breaker then use FirstOrDefault
var sorted = contents.OrderBy(c => c.Attributes.FirstOrDefault(a => a.Name == "name2")?.Value).ToList();
I've a JSON file like this:
{
"Groups": [
{
"UniqueId": "1",
"Name": "England",
"Members": [
{
"UniqueId": "Rooney",
"Name": "Rooney",
"JerseyNumber": "10",
"Position": "Forward"
},
{
"UniqueId": "Aquero",
"Name": "Aguero",
"JerseyNumber": "16",
"Position": "Forward"
},
{
"UniqueId": "Nani",
"Name": "Nani",
"JerseyNumber": "7",
"Position": "Midfielder"
}
]
}
]
}
I've been able to reach down to the Members array of JSON by this code:
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("Data2.json");
string jsonText = await FileIO.ReadTextAsync(file);
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonArray jsonArray = jsonObject["Groups"].GetArray()[0].GetObject()["Members"].GetArray();
I have the UniqueId of a Member and I want to search that member with UniqueId for its position within the "Members" array and then I want to delete that member. Suppose I've UniqueId="Nani", I want to search for that member with unique Id Nani and delete it.
I want the final result in JSON file as:
{
"Groups": [
{
"UniqueId": "1",
"Name": "England",
"Members": [
{
"UniqueId": "Rooney",
"Name": "Rooney",
"JerseyNumber": "10",
"Position": "Forward"
},
{
"UniqueId": "Aquero",
"Name": "Aguero",
"JerseyNumber": "16",
"Position": "Forward"
}
]
}
]
}
I think it will be better for you to create a class which matches your json tree. I am using .net 3.5 so i think i miss dll for json class you are using. But you will get the logic in this code below, comments will help you too
public class Groups // "Groups": [
{
public int UniqueId { get; set; } // "UniqueId": "1",
public String Name { get; set; } // "Name": "England",
public List<Member> ListMembers { get; set; } // "Members": [
public Groups(string json)
{
/* use your json object to get different data */
UniqueId = "Group UniqueId";
Name = "Group Name";
// get all member
foreach (jsonMember in jsonObject.Members)
{
Member member = new Member
{
UniqueId = "jsonMember UniqueId",
Name = "jsonMember Name",
JerseyNumber = "jsonMember JerseyNumber",
Position = "jsonMember Position",
};
ListMembers.Add(member);
}
}
public class Member // {"UniqueId":"Nani", "Name":"Nani", ... }
{
public string UniqueId { get; set; } // "UniqueId": "Aquero",
public String Name { get; set; } // "Name": "Aguero",
public int JerseyNumber { get; set; } // "JerseyNumber": "16",
public string Position { get; set; } // "Position": "Forward"
}
public void Delete(string UniqueId) // by example Delete("Nani")
{
ListMembers.RemoveAll(m => m.UniqueId == UniqueId);
}
}