How to put multiple values in Dictionary instances using LINQ? - c#

My Json Response is Following below:
{"d":
{"RowData":
[{"GenreId":11,"GenreName":"Musical","subjecturl":"subjecturl_1","logourl":"logourl_1"},
{"GenreId":12,"GenreName":"kids","subjecturl":"subjecturl_2","logourl":"logourl_2"},
{"GenreId":13,"GenreName":"other","subjecturl":"subjecturl_3","logourl":"logourl_3"},
{"GenreId":14,"GenreName":"Musical","subjecturl":"subjecturl_4","logourl":"logourl_4"},
{"GenreId":15,"GenreName":"Music","subjecturl":"subjecturl_5","logourl":"logourl_5"},
{"GenreId":16,"GenreName":"Faimaly","subjecturl":"subjecturl_6","logourl":"logourl_6"},
{"GenreId":17,"GenreName":"other","subjecturl":"subjecturl_7","logourl":"logourl_7"},
{"GenreId":18,"GenreName":"other","subjecturl":"subjecturl_8","logourl":"logourl_8"},
{"GenreId":19,"GenreName":"kids","subjecturl":"subjecturl_9","logourl":"logourl_9"},
{"GenreId":20,"GenreName":"Musical","subjecturl":"subjecturl_10","logourl":"logourl_10"},
{"GenreId":21,"GenreName":"other","subjecturl":"subjecturl_11","logourl":"logourl_11"}]}}
Using the above Response I tried to make like below Response :
{"rows": [{
"title": "Musical",
"items": [{"hdsubjecturl": "subjecturl_1"},{"hdsubjecturl": "subjecturl_4"},{"hdsubjecturl": "subjecturl_10"}]
},{
"title": "kids",
"items": [{"hdsubjecturl": "subjecturl_2"},{"hdsubjecturl": "subjecturl_9"}]
},{
"title": "Music",
"items": [{"hdsubjecturl": "subjecturl_5"}]
},{
"title": "other",
"items": [{"hdsubjecturl": "subjecturl_3"},{"hdsubjecturl": "subjecturl_7"},{"hdsubjecturl": "subjecturl_8"},{"hdsubjecturl": "subjecturl_11"}]
},{
"title": "Faimaly",
"items": [{"hdsubjecturl": "subjecturl_6"}]
}]
}
My Code is below :
JObject Root = JObject.Parse(jsonData["d"].ToString());
var unique = Root["RowData"].GroupBy(x => x["GenreName"]).Select(x => x.First()).ToList(); // here fetch 5 record
foreach (var un in unique)
{
var GenreName = new
{
title = un["GenreName"],
items = new
{
hdsubjecturl = "logourl"
}
};
var GenreNamereq = JsonConvert.SerializeObject(GenreName, Newtonsoft.Json.Formatting.Indented);
genstr.Append(GenreNamereq, 0, GenreNamereq.Length);
genstr.Append(",");
using (System.IO.StreamWriter file = new System.IO.StreamWriter(subdir + "\\GenreName.json"))
{
string st = genstr.ToString().Substring(0, (genstr.Length - 1));
file.WriteLine("{\n\"rows\": [\n" + st + "\n}"); //seasion number 21 terminate
file.Close();
}
}
Using above code my output is below for First Field :
{"rows":
[{
"title": "Musical",
"items": {
"hdsubjecturl": "logourl"
}
}]
}
Using below code I tried to fetch Multiple values using specific Field :
List<string> CategoryList = new List<string>();
var unique = Root["RowData"].GroupBy(x => x["GenreName"]).Select(x => x.First()).ToList(); // here fetch 8 record
foreach (var cat in unique)
{
CategoryList.Add(cat["GenreName"].ToString());
}
List<List<string>> myList = new List<List<string>>();
for (int i=0;i<CategoryList.Count();i++)
{
var results = from x in Root["RowData"]
where x["GenreName"].Value<string>() == CategoryList[i]
select x;
foreach (var token in results)
{
Console.WriteLine(token["logourl"]);
}
// myList.Add(results);
}
In the First code, I used JObject for fetching a Root node. But, using the above query it takes by default JTocken. So, I used foreach loop here.
I used Dictionary instances for JSON Creation. Using this code I successfully fetched hdsubjecturl in for loop. But, I don't know how to put multiple values in Dictionary instances. Because I get title fields only single times using a unique query and items fields inside a hdsubjetcurl is more than one. Does anyone know how it's possible?

You can group your RowData by GenreName token, then use ToDictionary method to get a result dictionary and map it to desired structure (with title and hdsubjecturl). Finally create a result object using JObject.FromObject
var json = JObject.Parse(jsonString);
var data = json["d"]?["RowData"]
.GroupBy(x => x["GenreName"], x => x["subjecturl"])
.ToDictionary(g => g.Key, g => g.ToList())
.Select(kvp => new { title = kvp.Key, items = kvp.Value.Select(x => new { hdsubjecturl = x }) });
var result = JObject.FromObject(new { rows = data });
Console.WriteLine(result);
It gives you the expected result.
Edit: according to comments, GroupBy and Select expressions should be updated to map more then one property in result title item
var data = json["d"]?["RowData"]
.GroupBy(x => x["GenreName"])
.ToDictionary(g => g.Key, g => g.ToList())
.Select(kvp => new
{
title = kvp.Key,
items = kvp.Value.Select(x => new { hdsubjecturl = x["subjecturl"], url = x["logourl"] })
});
var result = JObject.FromObject(new { rows = data });

Consider trying this code, (using Newtonsoft Json deserializer);
public partial class Root
{
public D D { get; set; }
}
public partial class D
{
public RowDatum[] RowData { get; set; }
}
public partial class RowDatum
{
public long GenreId { get; set; }
public string GenreName { get; set; }
public string Subjecturl { get; set; }
public string Logourl { get; set; }
}
public partial class Response
{
public Row[] Rows { get; set; }
}
public partial class Row
{
public string Title { get; set; }
public Item[] Items { get; set; }
}
public partial class Item
{
public string Hdsubjecturl { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var json =
#"{""d"":{""RowData"":[{""GenreId"":11,""GenreName"":""Musical"",""subjecturl"":""subjecturl_1"",""logourl"":""logourl_1""},{""GenreId"":12,""GenreName"":""kids"",""subjecturl"":""subjecturl_2"",""logourl"":""logourl_2""},{""GenreId"":13,""GenreName"":""other"",""subjecturl"":""subjecturl_3"",""logourl"":""logourl_3""},{""GenreId"":14,""GenreName"":""Musical"",""subjecturl"":""subjecturl_4"",""logourl"":""logourl_4""},{""GenreId"":15,""GenreName"":""Music"",""subjecturl"":""subjecturl_5"",""logourl"":""logourl_5""},{""GenreId"":16,""GenreName"":""Faimaly"",""subjecturl"":""subjecturl_6"",""logourl"":""logourl_6""},{""GenreId"":17,""GenreName"":""other"",""subjecturl"":""subjecturl_7"",""logourl"":""logourl_7""},{""GenreId"":18,""GenreName"":""other"",""subjecturl"":""subjecturl_8"",""logourl"":""logourl_8""},{""GenreId"":19,""GenreName"":""kids"",""subjecturl"":""subjecturl_9"",""logourl"":""logourl_9""},{""GenreId"":20,""GenreName"":""Musical"",""subjecturl"":""subjecturl_10"",""logourl"":""logourl_10""},{""GenreId"":21,""GenreName"":""other"",""subjecturl"":""subjecturl_11"",""logourl"":""logourl_11""}]}}";
var root = JsonConvert.DeserializeObject<Root>(json);
var rows = root.D.RowData.ToLookup(d => d.GenreName)
.Select(g => new Row()
{
Title = g.Key,
Items = g.ToList().Select(rd => new Item() {Hdsubjecturl = rd.Logourl}).ToArray()
}).ToArray();
var response = new Response()
{
Rows = rows
}; // reponse is the type of Json Response you wanted to achieve
Console.WriteLine();
}
}

Related

LiteDB Insert list with BsonRef

Hi and thanks in advance everyone!
I have a collection of the following objects:
public class ItemsModel
{
public List<int> IdCollection { get; set; }
public string Name { get; set; }
public int Weight { get; set; }
}
List<ItemsModel> col = ...;
I want to optimally store this with LiteDb and be able to modify the records.
Each ItemsModel has a unique Name+Weight set.
In the entire col, the elements of the IdCollection are also unique.
Body example:
List<ItemsModel>:
[{
IdCollection: [1,3,5,6,...],
Name: "first name",
Weight: 10
},
{
IdCollection: [2,4,...],
Name: "second name",
Weight: 5
}]
I want to index by Id
I want to expand into two tables for easy storage in LiteDb:
[{
_id: 1,
NameAndWeight: {&ref: "names"}
},
{
_id: 2,
NameAndWeight: {&ref: "names"}
},
{
_id: 3,
NameAndWeight: {&ref: "names"}
},
...
]
[{
Name: "first name",
Weight: 10
},
{
Name: "second name",
Weight: 5
}]
For this I have to make new storage classes:
public class ItemsModel
{
[BsonId]
public int Id { get; set; }
[BsonRef("names")]
public NamesModel NameAndWeight { get; set; }
}
public class NamesModel
{
[BsonId(true)]
public ObjectId Id { get; set; }
public string Name { get; set; }
public int Weight { get; set; }
}
But next step I'm having trouble...
Tell me, can I somehow save data using Insert array and Include in one operation?
Or should I use foreach to first write the NamesModel in "names" DB, get the generated _id, then write the ItemsModel with a link to the NamesModel already written to the database?
using (var db = new LiteDatabase(_strConnection))
{
var itemsDb = db.GetCollection<ItemsModel>("items");
var namesDb = db.GetCollection<NamesModel>("names");
itemsDb.EnsureIndex(x => x.Id, true);
foreach (var group in col)
{
var name = new NamesModel(group.Name, group.Weight);
namesDb.Insert(name);
var itemDb = group.IdCollection.Select(el => new ItemsModel(el, name));
var h = itemsDb.Insert(itemDb);
}
}
it is too long(
Now I did like this:
using (var db = new LiteDatabase(_strConnection))
{
var itemsDb = db.GetCollection<ItemsModel>("items");
var namesDb = db.GetCollection<NamesModel>("names");
itemsDb.EnsureIndex(x => x.Id, true);
namesDb.EnsureIndex(x => x.Name);
var temp = col.Select(el => (el.IdCollection, new NamesModel(el.Name, el.Weight))).ToList();
namesDb.Insert(temp.Select(el => el.Item2));
var temp2 = temp.SelectMany(gr => gr.IdCollection.Select(el => new ItemsModel(el, gr.Item2)));
eventsIdDB.Insert(temp2);
}
Performed basic operations in linq to reduce the number of hits in liteDb

How to GROUP BY using Iteration?

I'm trying to GROUP the JSON by BOARD and SUM the likes_count, but not sure how to approach this, since I can only access the Transaction class by looping through Root first?
public class Transaction
{
public string Post { get; set; }
public int board {get; set; }
public int Sent_from { get; set; }
public int likes_count { get; set; }
}
public class Root
{
public int Sent_to { get; set; }
public List<Transaction> Transactions { get; set; }
}
static async System.Threading.Tasks.Task Main(string[] args)
{
var json = "";
using (WebClient wc = new WebClient())
{
json = wc.DownloadString("xxxxxxx");
}
var obj = JsonConvert.DeserializeObject<List<Root>>(json);
foreach (var item in obj)
{
foreach (var child in item.Transactions)
{
// access sent_from, likes_count and post.
}
}
}
I would've normally used:
obj.GroupBy(t => t.post);
Here is a JSON Sample:
Sent_to: X,
total_received_likes: X,
Transactions: [
{
Post: "50776785",
board: "600",
Sent_from: 359716,
likes_count: 4,
},
{
Post: "5085129785",
board: "500",
Sent_from: 359716,
likes_count: 6,
},
{
Post: "506542785",
board: "500",
Sent_from: 359716,
likes_count: 9,
},
The expected output in this case:
15 likes in board 500
4 likes in board 600.
If you want to group the Transactions by board regardless of which Root they belong to and then calculate the sum of likes_count for each group, you may create a list using something like this:
var list = obj.SelectMany(r => r.Transactions)
.GroupBy(t => t.board)
.Select(g => new { Board = g.Key, TotalLikes = g.Sum(t => t.likes_count) })
.ToList();
..which you can then use like this:
foreach (var item in list)
{
Console.WriteLine($"{item.TotalLikes} like(s) in board {item.Board}.");
}
You can also do the same thing for each Root separately if you like:
foreach (var root in obj)
{
var list = root.Transactions
.GroupBy(t => t.board)
.Select(g => new { Board = g.Key, TotalLikes = g.Sum(t => t.likes_count) })
.ToList();
}

Cartesian Product of Anonymous type

I am working on code which will give Cartesian product of two anonymous types. These 2 anonymous types are generated from database.
Code for 1st anonymous type:
private IEnumerable<object> GetItem()
{
return _unitOfWork.GetRepository<Item>()
.ListAll()
.Select(x => new
{
itemId = x.Id,
itemName = x.Name
})
}
Code for 2nd anonymous type:
private IEnumerable<object> GetVenue()
{
return _unitOfWork.GetRepository<Venue>()
.ListAll()
.Select(x => new
{
locationName = x.Address.City,
venueId = x.VenueId,
venueName = x.Name
})
}
I have following method to get the data and perform Cartesian product and return the data.
public object GetRestrictLookupInfo(IEnumerable<int> lookupCombinations)
{
IEnumerable<object> restrictList = new List<object>();
if (lookupCombinations.Contains(1))
{
var tempProductProfileList = GetItem();
restrictList = tempProductProfileList.AsEnumerable();
}
if (lookupCombinations.Contains(2))
{
var tempProductGroupList = GetVenue();
restrictList = (from a in restrictList.AsEnumerable()
from b in tempProductGroupList.AsEnumerable()
select new { a, b });
}
return restrictList;
}
I have controller which calls this method and return data in json format.
Controller Code
public HttpResponseMessage GetData(IEnumerable<int> lookupCombinations)
{
var lookupRestrictInfo = _sellerService.GetRestrictLookupInfo(lookupCombinations);
return Request.CreateResponse(HttpStatusCode.OK, lookupRestrictInfo);
}
Response expected is:-
[ {
"itemId": 1,
"itemName": "Music",
"locationName": "Paris",
"venueId": 99,
"venueName": "Royal Festival Hall"
} ]
Response which I receive is
[ {
"a": {
"itemId": 1,
"itemName": "Music"
},
"b": {
"locationName": "Paris",
"venueId": 99,
"venueName": "Royal Festival Hall" } }]
I am not able to get the expected JSON string.
You should start with the simplest possible code that shows your problem; your code above has a lot of complexities that may (or may not) have anything to do with your problem. Is this about manipulating anonymous types? Doing a Cartesian product with LINQ? Converting an object to JSON?
Here's one possible answer to what you might be looking for; notice that you can pass around anonymous types using generics instead of object.
namespace AnonymousTypes
{
class Program
{
static string Serialize(object o)
{
var d = (dynamic)o;
return d.ItemId.ToString() + d.ItemName + d.VenueId.ToString() + d.LocationName + d.VenueName;
}
static string GetData<T>(IEnumerable<T> result)
{
var retval = new StringBuilder();
foreach (var r in result)
retval.Append(Serialize(r));
return retval.ToString();
}
static string GetRestrictLookupInfo()
{
var restrictList = new[] { new { Id = 1, Name = "Music" }, new { Id = 2, Name = "TV" } };
var tempProductGroupList = new[] { new { LocationName = "Paris", Id = 99, Name = "Royal Festival Hall" } };
var result = from item in restrictList
from venue in tempProductGroupList
select new
{
ItemId = item.Id,
ItemName = item.Name,
LocationName = venue.LocationName,
VenueId = venue.Id,
VenueName = venue.Name
};
return GetData(result);
}
public static string GetData()
{
return GetRestrictLookupInfo();
}
static void Main(string[] args)
{
var result = GetData();
}
}
}
If that's not what you're looking for, you might start with code that doesn't use anonymous types, such as
namespace AnonymousTypes
{
sealed class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
sealed class Venue
{
public string LocationName { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
sealed class ItemAndVenue
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public string LocationName { get; set; }
public int VenueId { get; set; }
public string VenueName { get; set; }
}
class Program
{
static IEnumerable<Item> GetItem()
{
return new[] { new Item { Id = 1, Name = "Music" } };
}
static IEnumerable<Venue> GetVenue()
{
return new[] { new Venue { LocationName = "Paris", Id = 99, Name = "Royal Festival Hall" } };
}
static IEnumerable<ItemAndVenue> GetRestrictLookupInfo()
{
var restrictList = GetItem();
var tempProductGroupList = GetVenue();
var result = from item in restrictList
from venue in tempProductGroupList
select new ItemAndVenue
{
ItemId = item.Id,
ItemName = item.Name,
LocationName = venue.LocationName,
VenueId = venue.Id,
VenueName = venue.Name
};
return result;
}
static string GetData()
{
var v = GetRestrictLookupInfo().First();
return v.ItemId.ToString() + v.ItemName + v.VenueId.ToString() + v.LocationName + v.VenueName;
}
static void Main(string[] args)
{
var result = GetData();
}
}
}
In order to produce a single item in the output you need to create a new type, named or anonymous. Since you are using objects rather than actual types, the quickest approach is to cast them to dynamic:
var tempProductGroupList = GetVenue();
restrictList = (from a in restrictList.Cast<dynamic>()
from b in tempProductGroupList.Cast<dynamic>()
select new {
itemId = (int)a.itemId,
itemName = (string)a.itemName,
locationName = (string)b.locationName,
venueId = (int)b.venueId,
venueName = (string)b.venueName
});
This code is tightly coupled to the code producing both lists, because it assumes the knowledge of the field names of types passed into it dynamically. Any change in the structure of source data must be followed by a change in the code making combinations. In addition, it defeats run-time checking, so you need to be very careful with this code.
Try to create a simple object instead of nesting:
select new { a.itemId, a.itemName, b.locationName }
Like an option:
public object GetRestrictLookupInfo(IEnumerable<int> lookupCombinations)
{
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
if (lookupCombinations.Contains(1))
{
var tmp = _unitOfWork.GetRepository<Item>()
.ListAll()
.Select(x => new
{
itemId = x.Id,
itemName = x.Name
})
.Select(x =>
{
var dic = new Dictionary<string, object>();
dic.Add(nameof(x.itemId), x.itemId);
dic.Add(nameof(x.itemName), x.itemName);
return dic;
});
result.AddRange(tmp);
}
if (lookupCombinations.Contains(2))
{
var tmp = _unitOfWork.GetRepository<Venue>()
.ListAll()
.Select(x => new
{
locationName = x.Address.City,
venueId = x.VenueId,
venueName = x.Name
})
.Select(x =>
{
var dic = new Dictionary<string, object>();
dic.Add(nameof(x.locationName), x.locationName);
dic.Add(nameof(x.venueId), x.venueId);
dic.Add(nameof(x.venueName), x.venueName);
return dic;
});
result = result.SelectMany(r => tmp.Select(t => r.Concat(t)));
}
return result;
}
It looks like some magic. I uses dictionary instead of object. It can be make in more clear way (extract few methods), but the idea should be clear.
Then, during serialization it will be presented as you need.

MongoDB .Net driver 2.0 Pull (remove element)

Can you help me to run correctly "Pull (remove)" with 2.0 driver.
I have a collection like this and I want to remove first follower named as fethiye by follower field.
{
"_id": ObjectId("554e05dfc90d3d4dfcaa2aea"),
"username": "bodrum",
"followerList": [
{
"_id": ObjectId("554e0625a51586362c33c6df"),
"follower": "fethiye",
"avatar": "fethiye.png"
},
{
"_id": ObjectId("554e0625a51586362c33c6df"),
"follower": "izmir",
"avatar": "izmir.png"
}
]
}
How can I fix this query?
var filter = new BsonDocument("username", "bodrum");
var update = Builders<Person>.Update.Pull("followerList:follower", "fethiye");
Person pr = collection.FindOneAndUpdateAsync(filter, update).Result;
Thanks.
When using a filter to remove array elements, you need to use the PullFilter builder instead of Pull (which matches whole elements).
var collection = db.GetCollection<Person>("people");
var filter = new BsonDocument("username", "bodrum");
var update = Builders<Person>.Update.PullFilter("followerList",
Builders<Follower>.Filter.Eq("follower", "fethiye"));
var result = collection.FindOneAndUpdateAsync(filter, update).Result;
Or somewhat more succinctly, using lambdas:
var update = Builders<Person>.Update.PullFilter(p => p.followerList,
f => f.follower == "fethiye");
var result = collection
.FindOneAndUpdateAsync(p => p.username == "bodrum", update).Result;
Assuming you have a collection name Person,
You can use PullFilter to remove the records from array
var filterBuilder = Builders<Person>.Filter.Eq(person => person.username, "bodrum");
var updateBuilder = Builders<Person>.Update.PullFilter(p => p.followerList,
Builders<Person>.Filter.Eq(per => per.follower, "fethiye"));
var updateResult = collection.UpdateOne(filterBuilder, updateBuilder);
Console.WriteLine(
$"MatchedCount: {updateResult.MatchedCount}, ModifiedCount: {updateResult.ModifiedCount}");
If we also need to remove array of values inside a filtered document we can replace the update builder with this line
var updateBuilder = Builders<Person>.Update.PullFilter(p => p.followerList,
Builders<Person>.Filter.In(per => per.follower, new List<string> {"fethiye", "izmir"}));
Also to save many document, updateOne can be replace with updateMany
var updateResult = collection.UpdateMany(filterBuilder, updateBuilder);
This is what i use to delete a nested array object
-parentpath: followerList
-propertie: follower
-value: fethiye.png
var filter = new BsonDocument("_id", ObjectId.Parse(id));
var updateValues = Builders<object>.Update.PullFilter(parentPath,
Builders<object>.Filter.Eq(propertie, value));
DatabaseCollection.FindOneAndUpdate(filter, updateValues);
Example to delete a deeper nested array object:
Let's delete the object with the name Doe
-parentPath: followerList.0.testArray
-propertie:name
-value:Doe
{
"_id": ObjectId("554e05dfc90d3d4dfcaa2aea"),
"username": "bodrum",
"followerList": [
{
"_id": ObjectId("554e0625a51586362c33c6df"),
"follower": "fethiye",
"testArray": [
{
"name":"John"
},
{
"name":"Doe"
},
{
"name":"Jason"
}
]
},
{
"_id": ObjectId("554e0625a51586362c33c6df"),
"follower": "izmir",
"avatar": "izmir.png"
}
]
}
may i offer a much simpler solution using MongoDB.Entities. the person and followers are stored in their own collections and represents a one-to-many relationship.
using System.Linq;
using MongoDB.Entities;
namespace StackOverflow
{
public class Person : Entity
{
public string Username { get; set; }
public Many<Follower> FollowerList { get; set; }
public Person() => this.InitOneToMany(() => FollowerList);
}
public class Follower : Entity
{
public string Name { get; set; }
public string Avatar { get; set; }
}
class Program
{
static void Main(string[] args)
{
new DB("followers");
var person1 = new Person { Username = "bodrum"};
person1.Save();
var follower1 = new Follower { Name = "fethiye", Avatar= "fethiye.png" };
follower1.Save();
var follower2 = new Follower { Name = "izmir", Avatar = "izmir.png" };
follower2.Save();
person1.FollowerList.Add(follower1);
person1.FollowerList.Add(follower2);
var fathiye = person1.FollowerList.Collection()
.Where(p => p.Name == "fethiye")
.FirstOrDefault();
person1.FollowerList.Remove(fathiye);
}
}
}

Is there any way to obtain following json result?

I have a datatable
classname Division Subject
I A English
I A Maths
I B English
II A English
i need the output as
[
{
"className":I,
Division:[
{
name:A,
subject:[
{
name:english
},
{
name:maths
}
]
},
{
name:B,
subject:[
{
name:English
}
]
}
]
},
{
"ClassName":II,
Division:[
{
name:A,
subject:[
{
name:english
}
]
}
]
}
]
Assuming you are starting with a DataTable like this:
DataTable table = new DataTable();
table.Columns.Add("className");
table.Columns.Add("Division");
table.Columns.Add("Subject");
table.Rows.Add("I", "A", "English");
table.Rows.Add("I", "A", "Maths");
table.Rows.Add("I", "B", "English");
table.Rows.Add("II", "A", "English");
You can get the output you want like this:
List<DataRow> rows = new List<DataRow>();
foreach (DataRow row in table.Rows)
rows.Add(row);
var result = rows.GroupBy(r => r["className"])
.Select(g => new
{
className = g.Key,
division = g.GroupBy(r => r["Division"])
.Select(g1 => new
{
name = g1.Key,
subject = g1.Select(r => new
{
name = r["Subject"]
})
})
});
string json = JsonConvert.SerializeObject(result, Formatting.Indented);
Console.WriteLine(json);
Working demo: https://dotnetfiddle.net/67mjiu
You got two options:
Create the JSON by hand (using a StringBuilder or JSON.NETs built in object types)
Create DTO (Data Transfer Objects) which looks like the wanted structure, fill them with data, and then serialize them.
DTOs:
public class Clazz
{
public string className { get; set; }
public Division[] Division { get; set; }
}
public class Division
{
public string name { get; set; }
public Subject[] subject { get; set; }
}
public class Subject
{
public string name { get; set; }
}
Your JSON is not valid. All names and string values must be escaped with quotes.

Categories

Resources