Foreach in List and return new empty list in condition - c#

I have create two class as below :
public class SearchResult
{
public int Id { get; set; }
public int Total { get; set; }
public IEnumerable<Book> Books { get; set; }
}
public class Book {
public int BookId { get; set; }
public string BookName { get; set; }
public string Publisher { get; set; } = string.Empty;
public string ISBNCode { get; set; } = string.Empty;
public DateTime PublishDate { get; set; } = DateTime.MinValue;
}
Initial Data as below:
{
"Id": 0,
"Total": 2,
"Books": [
{
"BookId": 1,
"BookName": "Book A",
"Publisher": "Peter",
"ISBNCode": "ISBN0001",
"PublishDate": "2022-03-03T10:19:23.9038822+00:00"
},
{
"BookId": 2,
"BookName": "Book C",
"Publisher": "Kate",
"ISBNCode": "ISBN0003",
"PublishDate": "2022-02-26T10:19:23.9039301+00:00"
}
]
}
I want to make the result if PublishDate > 2022-03-01 and then only keep BookId and PublishDate remain property need to empty, the expected output will be
{
"Id": 0,
"Total": 2,
"Books": [
{
"BookId": 1,
"BookName": "",
"Publisher": "",
"ISBNCode": "",
"PublishDate": "2022-03-03T10:19:23.9038822+00:00"
},
{
"BookId": 2,
"BookName": "Book C",
"Publisher": "Kate",
"ISBNCode": "ISBN0003",
"PublishDate": "2022-02-26T10:19:23.9039301+00:00"
}
]
}
For book class will have many properties and sublist in future, so I would like make a new book, just like this
searchResult.Books.Where(dt => dt.PublishDate > '2022-3-1').ToList().ForEach(
b => new Book {
BookId = b.BookId,
PublishDate = b.PublishDate
});
But I have no idea inside, can anyone advise about this ?
Thank you

I think it's a little strange to clear properties, maybe I don't get it completely, but..
You could create a filter, which will be used with Select:
private static Book ClearPropertiesAfterDate(Book book, DateTime date)
{
if(book.PublishDate > date)
return new Book { BookId = b.BookId, PublishDate = b.PublishDate }
else
return book;
}
// use select to transform each item.
// The ClearPropertiesAfterDate returns a new book (with only the id
// and publishDate when it was released after a certain date
// otherwise it returns the original book.
var booksFiltered = searchResult.Books.Select(dt =>
ClearPropertiesAfterDate(dt, '2022-3-1')).ToList();
'2022-3-1' should be a DateTime? Just should how you could transform items, didn't tested it in visualstudio or fiddle thingy

Related

Fluent Assertions between two collection class

I have a class with collection class inside
public class SearchResult {
public int Id { get; set; }
public int Total { get; set; }
public IEnumerable<Book> Books { get; set; }
}
public class Book {
public int BookId { get; set; }
public string BookName { get; set; }
public string Publisher { get; set; }
public string ISBNCode { get; set; }
public IList<catagory> Catagories { get; set; }
}
I have a question , if I create the other object , with same structure of SearchResult and I want to copy SearchResult to SearchResultClone, which inside Books only copy BookId and BookName remain is empty.
Just like below
{
"Id": 0,
"Total": 3,
"Books": [
{
"BookId": 1,
"BookName": "Book A",
"Publisher": "",
"ISBNCode": "",
"Catagories": []
},
{
"BookId": 2,
"BookName": "Book B",
"Publisher": "",
"ISBNCode": "",
"Catagories": []
},
{
"BookId": 3,
"BookName": "Book C",
"Publisher": "",
"ISBNCode": "",
"Catagories": []
}
]
}
Event the original result have value of Publisher, ISBNCode ..etc
How to do it in LINQ ?
My second question is , if I want to make a fluent assertions as above object
var result = await sut.search(query);
result.Should().BeEquivalentTo ({the SearchResultClone })
How to write this fluent assertion ?
You need to create new instances of the classes based on the old instances:
var ans = result.Select(sr => new SearchResult {
Id = sr.Id,
Total = sr.Total,
Books = sr.Books.Select(b => new Book { BookId = b.BookId, BookName = b.BookName }).ToList()
}).ToList();
result.Should().BeEquivalentTo ({the SearchResultClone })
How to write this fluent assertion ?
If your expectation (the object you pass into BeEquivalentTo) is of the type SearchResult, then FA will try to compare the empty values of ISBN to the same property on the sut. You can solve that by doing something like:
sut.Should().BeEquivalentTo(new
{
Id = "some value",
Total = 123,
Books = new[]
{
new
{
BookId = 123,
BookName = "some book"
}
}
});

Create json object with multiple array in c#

I want to create JSON object with following format:-
{
"result": [
{
"name": "John",
"address": "US",
},
{
"name": "Josh",
"address": "Japan",
}
],
"error": [
{
"message": "error-message"
}
],
"success": [
{
"message": "success-message"
}
]
}
I have tried the following, but it doesn't help me.
dynamic record = new { result = new {name="", address=""},
error = new {message=""},
success = new {message=""} };
Update 1:-
Here is my code:-
List addressList = new List();
// Loop over items within the container and URI.
foreach (var item in items)
{
dynamic record = new { result = new object[] {
new {name = item.name, address = item.address} } };
addressList.Add(record);
}
Result:-
[ {
"result": [
{
"name": "John",
"address": "US"
}
]
},
{
"result": [
{
"name": "Jack",
"address": "CA"
}
]
}
]
Expected json result:-
[{
"result": [{
"name": "John",
"address": "US"
}]
},
{
"result": [{
"name": "Jack",
"address": "CA"
}],
"error": [{
"message": "error-message"
}],
"success": [{
"message": "success-message"
}]
}
]
How do I update my code to get above expected json result?
You...create arrays. You're not doing that. You're creating individual objects.
Something along the lines of:
dynamic record = new {
result = new object[] {
new {name = "John", address = "US"},
new {name = "Josh", address = "Japan"}
},
error = new object[] /*...*/,
success = new object[] /*...*/
};
If you want exactly JSON, then newtonsoft.Json makes it easier:
Json json = new Json();
json.result = new object[] {
new {name = "John", address = "US"},
new {name = "Josh", address = "Japan"}
};
// json.error = ... and so on
string output = JsonConvert.SerializeObject(product);
The output you will have is:
{
"result": [
{
"name": "John",
"address": "US",
},
{
"name": "Josh",
"address": "Japan",
}
],
"error": [
{
...
}
]
}
To deserialize it back, use:
Json deserializedJson = JsonConvert.DeserializeObject<Json>(output);
you are not creating an array
if you want to create JSON arrays from c# you have to use the following POCO
public class Result
{
public string name { get; set; }
public string address { get; set; }
}
public class Error
{
public string message { get; set; }
}
public class Success
{
public string message { get; set; }
}
public class RootObject
{
public List<Result> result { get; set; }
public List<Error> error { get; set; }
public List<Success> success { get; set; }
}
and then use Json.net
var json = JsonConvert.SerializeObject( "your instance of the root Object")
//You need to make this class structure first
public class Response
{
public List<Result> result { get; set; }
public List<Error> error { get; set; }
public List<Success> success { get; set; }
}
public class Result
{
public string name { get; set; }
public string address { get; set; }
}
public class Error
{
public string message { get; set; }
}
public class Success
{
public string message { get; set; }
}
// And then you can use it like this
var response = new Response()
{
result = new List<Result>
{
new Result() {name = "Jhon", address = "US"},
new Result() {name = "Jhon", address = "US"},
},
error = new List<Error>()
{
new Error() {message = "error-message 1"},
new Error() {message = "error-message 2"}
},
success = new List<Success>()
{
new Success(){message = "success-message 1"},
new Success(){message = "success-message 2"},
}
};
The Model Class
public class MegaMenu
{
public int department_id { get; set; }
public string department_name { get; set; }
public List<SectionListData> sectionListData { get; set; }
}
public class SectionListData
{
public int section_id { get; set; }
public string section_name { get; set; }
public List<ItemHeadList> itemHeadList { get; set; }
}
public class ItemHeadList
{
public int item_head_id { get; set; }
public string item_name { get; set; }
}
public class WrapperMegaMenu
{
public List<MegaMenu> megaMenuList { get; set; }
public string error { get; set; }
}
The Services
dept_result is the array of all department,section_result is the array of all section,Item_result is the array of all items
List<MegaMenu> listmenu = new List<MegaMenu>();
foreach (var each_dept in dept_result)
{
MegaMenu megaMenu = new MegaMenu();
megaMenu.department_id = each_dept.shopdepartment_id;
megaMenu.department_name = each_dept.name_en;
var temSectionList = section_result
.Where(item => item.shopdepartment_id == each_dept.shopdepartment_id).ToList().Select(sectionData => new SectionListData
{
section_id = sectionData.shopsection_id,
section_name = sectionData.name_en,
itemHeadList = Item_result.Where(itemHead => itemHead.shopsection_id == sectionData.shopsection_id).ToList().Select(itemHeadData => new ItemHeadList {
item_head_id = itemHeadData.item_head_id,
item_name = itemHeadData.name_en
}).ToList()
}).ToList();
megaMenu.sectionListData = temSectionList;
listmenu.Add(megaMenu);
}
//wrapperDept.departmentList = dept_result.ToList();
wrapper.megaMenuList = listmenu.ToList();
Result
{
"megaMenuList": [
{
"department_id": 71,
"department_name": "Baby's Hygiene",
"sectionListData": [
{
"section_id": 56,
"section_name": "Diapers",
"itemHeadList": []
},
{
"section_id": 57,
"section_name": "Wipes",
"itemHeadList": [
{
"item_head_id": 142,
"item_name": "Telivision"
}
]
}
]
}
]
}

Use Linq or C# to parse Json

I am getting familiar with C# and Linq and appreciate any help. It should be easy for someone who works with it. I have a Json object that returns contact information. I also have a list of ids. I need to compare the list to the Json object and wherever the value in the list matches the userclientcode in the Json object, I need to extract the following information (only for the matches):
clienttaxonomy (if not empty)
fullname (if not empty)
[0]contactdata ( -> email if not null or empty)
[1]contactdata (-> address if not null or empty)
[2]contactdata (-> phone number if not null or empty)
First List
var fileContactIds = new List<string> { "5678765", "2135123", "12341234", "341234123", "12341234123", "2341234123", "341234123", "123412341", "13342354",
"12342341", "123412322", "163341234", "2345234115", "8967896", "75626234 };
JSON object returned with:
return JsonConvert.DeserializeObject<RelatedContacts>(json)?.list;
This is the Json object:
[![Json object][1]][1]
This is the Json string (unescaped):
{
"type": "com.kurtosys.api.userprofile.domain.RelatedContactList",
"list": [{
"objectlistid": 5678765,
"objectlisttypeid": 4567876,
"objectlistname": "ALL.National",
"clienttaxonomyid": 765677,
"clienttaxonomy": "National Wholesaler",
"order": 1,
"contacts": [{
"personid": 7654345678,
"fullname": "Person Jallo",
"userid": 876567,
"userclientcode": "341234123",
"contactdetails": [{
"contactid": 8765567,
"contacttypeid": 4565,
"contactdata": "person.contact#site.com"
}, {
"contactid": 876545678,
"contacttypeid": 4565,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 87654567,
"contacttypeid": 4584,
"contactdata": "410-413-2640"
}]
}]
}, {
"objectlistid": 765678,
"objectlisttypeid": 40400461,
"objectlistname": "RM.Internal",
"clienttaxonomyid": 7567898,
"clienttaxonomy": "Internal Regional Wholesaler",
"order": 2,
"contacts": [{
"personid": 56789876,
"fullname": "Jackson Man",
"userid": 876567,
"userclientcode": "1012275",
"contactdetails": [{
"contactid": 309598309,
"contacttypeid": 76546,
"contactdata": "mister.jackson##site.com.com"
}, {
"contactid": 876567,
"contacttypeid": 4581,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 876567,
"contacttypeid": 2342,
"contactdata": "123-413-2604"
}]
}]
}, {
"objectlistid": 309571364,
"objectlisttypeid": 40400461,
"objectlistname": "RM.External",
"clienttaxonomyid": 309580710,
"clienttaxonomy": "External Regional Wholesaler",
"order": 3,
"contacts": [{
"personid": 302736188,
"fullname": "Phal Sumi",
"userid": 303826019,
"userclientcode": "163341234",
"contactdetails": [{
"contactid": 309598253,
"contacttypeid": 2342,
"contactdata": "misters.emailas#site.com"
}, {
"contactid": 309611930,
"contacttypeid": 2342,
"contactdata": "Baltimore,MD,21209,United States"
}, {
"contactid": 34234132,
"contacttypeid": 3422,
"contactdata": "342-803-1793"
}]
}]
}]
}
How do I
1] Select using Linq and Lambdas and put in a list fullname, email, address etc from the deserialized object ?
2]compare with first list and only transfer those items where the userclientcode == the number in list A.
I have tried:
var query5 = relatedContact.Where(s => s.objectlistid == Convert.ToInt64(contacts.Select(t => t.id)))
var selected = relatedContact.Where(p => p.contacts
.Any(a => fileContactIds.Contains(p.contacts))
.ToList();
var query2 = relatedContact.Where(s => s.objectlistid == Convert.ToInt64(contacts.Select(t => t.id)))
.Select(s => new
{
Description = s.clienttaxonomy,
Fullname = s.contacts[0].fullname,
Email = s.contacts[0].contactdetails[0].contactdata,
Address = s.contacts[0].contactdetails[1].contactdata,
PhoneNumber = s.contacts[0].contactdetails[2].contactdata
});
But don't really know what I'm doing it seems. Any suggestions on how to get the required sections ? I think part of the reason is that the contactdata is a list.
Thanks all
You can create a classes for the desearlization of JSON Object like this
public class Rootobject
{
public string type { get; set; }
public List[] list { get; set; }
}
public class List
{
public int objectlistid { get; set; }
public int objectlisttypeid { get; set; }
public string objectlistname { get; set; }
public int clienttaxonomyid { get; set; }
public string clienttaxonomy { get; set; }
public int order { get; set; }
public Contact[] contacts { get; set; }
}
public class Contact
{
public long personid { get; set; }
public string fullname { get; set; }
public int userid { get; set; }
public string userclientcode { get; set; }
public Contactdetail[] contactdetails { get; set; }
}
public class Contactdetail
{
public int contactid { get; set; }
public int contacttypeid { get; set; }
public string contactdata { get; set; }
}
And then to extract the selected information we can also create a another class like
public class ExtractedInfo
{
public string ocClientTaxonomy { get; set; }
public string ocFullName { get; set; }
public CTDetails ocContactDetails { get; set; }
}
public class CTDetails
{
public string ocCTAddress { get; set; }
public string ocCTEmail { get; set; }
public string ocCTPhoneNumber { get; set; }
}
Now we have to find all the data from JSON
var fileContactIds = new List<string> { "5678765", "2135123", "12341234", "341234123", "12341234123", "2341234123", "341234123", "123412341", "13342354", "12342341", "123412322", "163341234", "2345234115", "8967896", "75626234" };
//Read JSON from txt file. You can do it by your way
string myjson = File.ReadAllText("Some.txt");
string ctphno, ctadd, ctemail, cltax, ctfullname;
List<ExtractedInfo> ei = new List<ExtractedInfo>();
CTDetails ctdtl = new CTDetails();
ExtractedInfo eiex = new ExtractedInfo();
//Deserialize the JSON string to Object.
Rootobject AllData = JsonConvert.DeserializeObject<Rootobject>(myjson);
//Finding all data in List Class
foreach(List lst in AllData.list)
{
cltax = lst.clienttaxonomy; // you can directly put eiex.ocClientTaxonomy = lst.clienttaxonomy;
foreach(Contact ct in lst.contacts)
{
//To check if value in the list matches the objectlistid in the Json object
if(fileContactIds.Contains(lst.objectlistid.ToString()))
{
ctfullname = ct.fullname; // you can directly put eiex.ocFullName = ct.fullname;
foreach(Contactdetail ctd in ct.contactdetails)
{
//Here we are trying to find the Match for Email.
if(Regex.IsMatch(ctd.contactdata, #"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase))
{
ctemail = ctd.contactdata;
ctdtl.ocCTEmail = ctemail;
}
//Here We trying to find the match for Phone Number.
else if(Regex.IsMatch(ctd.contactdata, #"\(?\d{3}\)?-? *\d{3}-? *-?\d{4}", RegexOptions.IgnoreCase))
{
ctphno = ctd.contactdata;
ctdtl.ocCTPhoneNumber = ctphno;
}
//If NOthing matches than it might be address (Assumed)
else
{
ctadd = ctd.contactdata;
ctdtl.ocCTAddress = ctadd;
}
}
eiex.ocFullName = ctfullname;
}
}
eiex.ocClientTaxonomy = cltax;
eiex.ocContactDetails = ctdtl;
ei.Add(eiex);
}
Hope this helps and fit in your requirements.

Querying nested objects using linq query with join

I have the following json structure that I am getting from an api:
{
"event_instance": [
{
"id": 55551244,
"event_id": 11112,
"name": "Brown Belt Karate Class",
"staff_members": [
{
"id": 12345,
"name": "John Smith"
}
],
"people": [
{
"id": 111,
"name": "Jane Doe"
},
{
"id": 222,
"name": "Josh Smith"
},
{
"id": 333,
"name": "Ben Johnson"
}
],
"visits": [
{
"id": 1234578,
"person_id": 111,
"state": "completed",
"status": "complete"
},
{
"id": 1239865,
"person_id": 222,
"state": "completed",
"status": "complete"
},
{
"id": 1239865,
"person_id": 333,
"state": "canceled",
"status": "cancel"
}
]
}
]
}
I am deserializing this into the following .net objects using JSON.NET:
[JsonObjectAttribute("event_instance")]
public class EventInstance
{
[JsonPropertyAttribute("id")]
public int Id { get; set; }
[JsonPropertyAttribute("event_id")]
public int EventId { get; set; }
[JsonPropertyAttribute("name")]
public string Name { get; set; }
[JsonPropertyAttribute("staff_members")]
public List<StaffMember> StaffMembers { get; set; }
[JsonPropertyAttribute("visits")]
public List<Visit> Visits { get; set; }
[JsonPropertyAttribute("people")]
public List<Student> Students { get; set; }
}
[JsonObjectAttribute("staff_members")]
public class StaffMember
{
[JsonPropertyAttribute("id")]
public int Id { get; set; }
[JsonPropertyAttribute("name")]
public string Name { get; set; }
}
[JsonObjectAttribute("people")]
public class People
{
[JsonPropertyAttribute("id")]
public int Id { get; set; }
[JsonPropertyAttribute("name")]
public string Name { get; set; }
}
[JsonObjectAttribute("visits")]
public class Visits
{
[JsonPropertyAttribute("id")]
public int Id { get; set; }
[JsonPropertyAttribute("person_id")]
public int PersonId { get; set; }
[JsonPropertyAttribute("state")]
public string State { get; set; }
[JsonPropertyAttribute("status")]
public string Status { get; set; }
}
I am using the following code to de-serialize:
var event = (EventInstance)JsonConvert.DeserializeObject(json, typeof(EventInstance));
The above works fine and gives me an accurate object representation of the above json structure. Now I am trying to query this event object to filter/project to a new structure that I can then serialize back to json and send down to the browser. I need to return a list of students for the event that are in a state of "completed" and a status of "complete". As you can see, the people array ties to the visits array (with id and person_id). I would like to produce the following simple output:
11112, Brown Belt Karate Class, John Smith, 111, Jane Doe
11112, Brown Belt Karate Class, John Smith, 222, Josh Smith
I have tried something like this:
var studentList = from theClass in event
from staff in theClass.StaffMembers
from student in theClass.People
from visits in theClass.Visits
where visits.Status == "complete"
&& visits.State == "completed"
select new
{
event_id = theClass.EventId
class_name = theClass.Name,
instructor_name = staff.Name,
student_id = student.Id,
student_name = student.Name
};
string _data = JsonConvert.SerializeObject(studentList);
Naturally this produces duplicate student names. I am new to linq. Basically I need to join/tie the people and visits array so I just get back a single student for that id, along with the root data for this event. Any advice on a better way to do this is much appreciated too!
The trick is to join the students and visits into a collection that contains data of both:
from ei in eventInstances
from sm in ei.StaffMembers
from x in
(from vi in ei.Visits
join st in ei.Students on vi.PersonId equals st.Id
select new { vi, st }) // Here you get students and visits side-by-side
select new
{
ei.EventId,
Event = ei.Name,
StaffMemeber = sm.Name,
PersonId = x.st.Id,
Student = x.st.Name
}

How can I return data in this specific way

I am building an angularjs app with a c# backend with dapper micro orm which gets me data from the database.
I wanted the data returned to look like this:
[{
"CategoryId": 1,
"CategoryName": "cat1",
"Items": [{
"ItemId": 1,
"ItemName": "Item1"
}, {
"ItemId": 2,
"ItemName": "Item2"
}]
}, {
"CategoryId": 2,
"CategoryName": "cat2",
"Items": [{
"ItemId": 3,
"ItemName": "Item3"
}, {
"ItemId": 4,
"ItemName": "Item4"
}]
}
]
but this is what my data looks like
[{
"CategoryId": 1,
"CategoryName": "cat1",
"Items": {
"ItemId": 1,
"ItemName": "Item1"
}
}, {
"CategoryId": 1,
"CategoryName": "cat1",
"Items": {
"ItemId": 2,
"ItemName": "Item2"
}
},
{
"CategoryId": 2,
"CategoryName": "cat2",
"Items": {
"ItemId": 3,
"ItemName": "Item3"
}
},
{
"CategoryId": 2,
"CategoryName": "cat2",
"Items": {
"ItemId": 4,
"ItemName": "Item4"
}
}
]
This is what I have in my repository:
public IEnumerable<CategoryModel> GetAllCategories()
{
using (var conn = ConnectionSettings.GetSqlConnection())
{
const string sql = #" SELECT
c.CategoryName,
c.CategoryId,
i.ItemId,
i.ItemName,
i.CategoryId
from Category c
INNER JOIN item i ON c.CategoryId = i.CategoryId";
var categoriesList = conn.Query<CategoryModel, ItemModel, CategoryModel>(sql, (cat, it) =>
{
cat.Item = it;
return cat;
}, splitOn: "ItemId");
return categoriesList;
}
}
And these are my Category and Item Models
public class CategoryModel
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public ItemModel Item { get; set; }
}
public class ItemModel
{
public int ItemId { get; set; }
public int CategoryId { get; set; }
public string ItemName { get; set; }
}
Could someone please point me in the right direction?
Please let me know what I am doing wrong here.
Thanks in advance
I would suggest a following approach to achieve the expected result:
Modify the entities as shown below, use Newtonsoft Json attributes to ignore the CategoryId in the ItemModel, to avoid the serialization
[JsonObject]
public class CategoryModel
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public IEnumerable<ItemModel> Items { get; set; }
}
[JsonObject]
public class ItemModel
{
public int ItemId { get; set; }
[JsonIgnore]
public int CategoryId { get; set; }
public string ItemName { get; set; }
}
Now for fetching data, since its one to many mapping inside the Category Model, which contains multiple Item Model, use the QueryMultiple to fetch both the result sets separately, code will look like:
public IEnumerable<CategoryModel> GetAllCategories()
{
using (var conn = ConnectionSettings.GetSqlConnection())
{
const string sql = #" SELECT
c.CategoryName,
c.CategoryId from Category c;
SELECT
i.ItemId,
i.ItemName,
i.CategoryId
from item i";
var reader = conn.QueryMultiple(sql);
IEnumerable<CategoryModel> categoriesList = reader.Read<CategoryModel>();
IEnumerable<ItemModel> itemList = reader.Read<ItemModel>();
foreach(Category c in categoriesList)
{
c.items = itemList.Where(i => i.CategoryId = c.CategoryId)
}
return categoriesList;
}
}

Categories