I have two sql records with different Address, I'm trying to make it as one record by using sublist
public class spproperty
{
public string Name{ get; set; }
public string Addr{ get; set; }
public int ID{ get; set; }
}
List<spproperty> lst = new List<spproperty>();
lst = db.sp_getDetails(inputParameter).ToList();//gets result from stored procedure as in example
Example:
Name Addr ID
John Florida 234
John Arizona 234
Expected Output in json from list
[
{
"Name": "John",
"Addresses" : {
"Addr" : "Florida",
"Addr" : "Arizona"
},
"ID": 234,
}
]
I tried in xelement with dataset it worked, Any suggestions with list
You can group by Name and ID then make the desired formatted list using linq. I think the following code will work for your scenario:
var desiredList = lst.GroupBy(x => new { Name = x.Name, ID = x.ID })
.Select(x => new
{
Name = x.FirstOrDefault().Name,
Addresses = x.Select(y => y.Addr).ToList(),
ID = x.FirstOrDefault().ID
}).ToList();
After that you can convert the result to Json if you want.
Related
I want to create one list with one Id and multiple ProviderId values like
Id ProviderId
1 "val1"
1 "val2"
I have a model class as per below :
public class Model
{
[JsonProperty]
public string Id { get; set; }
[JsonProperty]
public List<PrefDictionary> ProviderId { get; set; }
}
Now I have created one list as per below :
List<PrefDictionary> PrefData = data.Select(p => new PrefDictionary()
{
_1 = p.PrefDictionary._1,
_2 = p.PrefDictionary._2
}).ToList();
Here in data I am getting whole json format data and one node is like this below for PrefDictionary.
data = {
Id : 1,
PrefDictionary{
1: "Val1",
2: "Val2"
}}
Now then I have created one more list as per below :
List<Model> PP = data.Select(p => new Model()
{
Id = p.Id,
ProviderId = PrefData.Select(x => new PrefDictionary()
{
_1 = x._1,
_2 = x._2
}).ToList(),
}).ToList();
}
But the problem is I am getting empty in second column list in first I am getting Id but not getting any value in second column.
I'm not 100% I understand JSON format you are expecting. However, if you want a list of providers - each with a list of preferences - then I think you'll need another class to get this to serialize properly:
public class Model
{
[JsonProperty]
public List<Providers> providers { get; set; }
}
public class Providers
{
[JsonProperty]
public string Id { get; set; }
[JsonProperty]
public List<PrefDictionary> ProviderId { get; set; }
}
This should give you the JSON output:
{
"Providers": [
{
"ID": 1,
"PrefDictionary": [
{
"Val1": "",
"Val2": ""
}
]
},
{
"ID": 2,
"PrefDictionary": [
{
"Val1": "",
"Val2": ""
}
]
}
]
}
I suspect the problem could be the way how you deserialize your data object.
Based on your code, I've created the result that contains the PrefDirectonary.
.
However, one thing I did for the data variable was to make an object like this,
PrefDictionary pd = new PrefDictionary
{
_1 = "Value1",
_2 = "Value2"
};
List<TestObject> data = new List<TestObject>() {
new TestObject
{
Id = "1",
PrefDictionary = pd
}
};
It will be helpful to show us how you deserialize the JSON data object.
Problem description:
I have a scenario of List of Manufacturers each contain a ManufacturerId and a nested list of Products, which contain a ProductId and a nested list of Qualities, which contain a QualityId and a Price.
--Manufacturers (List)
----ManufacturerId (string)
----Products (List)
------ProductId (string)
------Qualities (List)
-QualityId (string)
-Price (decimal)
Or
class Manufacturer { string ManufacturerId { get; set; } IEnumerable<Product> Products { get; set; } }
class Product { string ProductId { get; set; } IEnumerable<Quality> Qualities { get; set; } }
class Quality { string QualityId { get; set; } decimal Price { get; set; } }
My goal:
Choose one manufacture and one product, and build a list of its chosen product's qualities List<string> where each item is a key constructed by $"{ManufacturerId}-{ProductId}-{QualityId}" key.
How to choose the manufacture and product:
Prioritized by the products from all the manufacturers with order by a string[] ProductPriotizeList
=> new[] { "P1", "P8", "P5", "P2" ... };
Ordered by cheapest price and get its QualityId.
Construct the List<string> keys of $"{ManufacturerId}-{ProductId}-{QualityId}" by the selected QualityId siblings (Note that the each of the selected keys will have the same ManufacturerId and ProductId and only vary by QualityId).
I tried (and it working):
I've created a class called FlattenQuality contain the Quality properties and added the ManufacturerId and the ProductId to it (by looping each of the manufacturers and each of the products).
class FlattenQuality
{
string QualityId { get; set; }
string ManufacturerId { get; set; }
string ProductId { get; set; }
decimal Price { get; set; }
string Key { get { return $"{ManufacturerId}-{ProductId}-{QualityId}"; }
}
Then constructed a list of FlattenQuality by SelectMany over the manufacturers and SelectMany over the products:
List<FlattenQuality> flattenQualities = BuildFlattenQuality(..);
Then the resulted selected keys list:
List<string> selected = flattenQualities.OrderBy(x => Array.IndexOf(ProductPriotizeList, x.ProductId)).ThenBy(x => x.Price).Select(x => x.MyKey).ToList();
For Example:
{
"Manufacturers": [
{
"ManufacturerId": 1,
"Products": [
{
"ProductId": P1,
"Qualities": [
{
"QualityId": 1,
"Price": 10
},
{
"QualityId": 2,
"Price": 20
}]
}]
},
{
"ManufacturerId": 2,
"Products": [
{
"ProductId": P1,
"Qualities": [
{
"QualityId": 1,
"Price": 15
},
{
"QualityId": 2,
"Price": 30
}]
}]
}]
}
Output should be:
{
"Keys": [
"1-1-1", //The QualityId 1 of productId 1 of ManuId 1 is the cheapest
"2-1-1" //The cheapest sibling
]
}
My Question:
How to achieve the same result of selected keys without to pollute my app with additional model? and without iterating all of the list again.
What you want to do is flatten your data. To do that:
var records =
manufacturers.SelectMany(m =>
m.Products.SelectMany(p =>
p.Qualities.Select(q => new
{
ManufacturerId = m.ManufacturerId,
ProductId = p.ProductId,
QualityId = q.QualityId,
Price = q.Price,
Key = string.Join("-", new string [] {m.ManufacturerId, p.ProductId, q.QualityId })
})
)
);
Then apply your ordering logic:
records.OrderBy(x => Array.IndexOf(productPriotizeList, x.ProductId))
.ThenBy(x => x.Price);
See a working demo here.
This question already has answers here:
C# - code to order by a property using the property name as a string [duplicate]
(10 answers)
Closed 4 years ago.
I have a list of ListUser class objects. I need to be able to pass in a String value and order by that column in ascending or descending order using text expression. Everything I have seen that uses Lambda expressions, has the object property as a strongly typed value, How can I achieve this by adding in "firstname descending" as a parameter ?
The code is as follows
namespace SortLists
{
class ListUser
{
public int id { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public string company { get; set; }
public string phonenumber { get; set; }
}
class Program
{
static void Main(string[] args)
{
var user1 = new ListUser() { id = 1, firstname = "James", lastname = "Smith", company = "Code Logic", phonenumber = "01235 566 456" };
var user2 = new ListUser() { id = 1, firstname = "Chris", lastname = "Andrews", company = "Adobe", phonenumber = "01235 566 456" };
var user3 = new ListUser() { id = 1, firstname = "Paul", lastname = "Jones", company = "Microsoft", phonenumber = "01235 566 456" };
var user4 = new ListUser() { id = 1, firstname = "Peter", lastname = "Williams", company = "Apple", phonenumber = "01235 566 456" };
List<ListUser> users = new List<ListUser>()
{
user1, user2, user3, user4
};
}
}
Add reference to nuget package:
https://www.nuget.org/packages/System.Linq.Dynamic/
Add using System.Linq.Dynamic; at the top.
Use var usersSorted = users.AsQueryable().OrderBy("firstname ASC").ToList();
It's easy with a dictionary. Just start with this:
var sortBy = new Dictionary<string, Func<IEnumerable<ListUser>, IEnumerable<ListUser>>>()
{
{ "firstname", lus => lus.OrderBy(lu => lu.firstname) },
{ "lastname", lus => lus.OrderBy(lu => lu.lastname) },
{ "company", lus => lus.OrderBy(lu => lu.company) },
{ "phonenumber", lus => lus.OrderBy(lu => lu.phonenumber) },
};
Then you can easily sort like this:
List<ListUser> sorted = sortBy["firstname"](users).ToList();
If you want it descending just do this:
List<ListUser> sorted = sortBy["firstname"](users).Reverse().ToList();
Just structure your sort method like so:
if(stringPassed == "firstname")
{
List<ListUser> sortedListUser = listUser.OrderBy(p=>p.firstName).ToList();
}
else if(...) // and so on
if you want to order them by desc order just use LINQ's .OrderByDescending method.
The other cool approach may be that you set your properties to be objects with
string value;
string name;
and loop your input string with reflection towards the properties in your class and get the one you want and order it. It's a fancy way to impress your teacher xaxa.
I am trying to generate json string for the hierarchy like below:
Company(select * from Company)
Department(select * from Department)
Employee(select * from Employee)
Each of the above query will return fields like below:
Company Fields - (Id,Name,Location)
Department Fields - (Id,Name,CompanyId)
Employee Fields - (Id,Name,DepartmentId)
Now I am trying to generate JSON string for above entities like below:
Expected output:
{
"Id": "",
"Name": "",
"Location": "",
"Department":
{
"Id": "",
"Name": "",
"CompanyId": "",
"Employee" :
{
"Id": "",
"Name": "",
"DepartmentId": "",
}
}
}
Code:
public string GetData(Child model,List<Parent> parents)
{
var fields = new List<string[]>();
if (parents != null)
{
foreach (var parent in parents)
{
var columns = GetColumns(parent); //returns string[] of columns
fields.Add(columns);
}
}
fields.Add(GetColumns(model));
string json = JsonConvert.SerializeObject(fields.ToDictionary(key => key, v => string.Empty),
Formatting.Indented);
return json;
}
Now when I don't have any parents and want to generate json string for only child then below code is working fine:
string json = JsonConvert.SerializeObject(fields.ToDictionary(key => key, v => string.Empty),Formatting.Indented)
Output :
{
"Id": "",
"Name": "",
"Location": "",
}
But now I want to generate JSON for my hierarchy with any such inbuilt way.
I know I can loop,append and create json string but I want to do this in better way like I have done for my child.
Update:
public class Child
{
public string Name { get; set; } // Contains Employee
//Other properties and info related to process sql query and connection string
}
public class Parent
{
public string Name { get; set; } // Contains Company,Department.
public string SqlQuery { get; set; } // query related to Company and Department.
//Other properties and info related to connection string
}
I created a class that holds the Information similarly to what you proposed, in a child-parent structure. I also added a custom little Parser that works recursively. Maybe that's what you need and/or what gives you the ideas you need to fix your problem.
I also altered the output a little bit, by adding the angled brackets ( "[ ]" ). I think that's what you will need with multiple children. At least that's what the JSON validator tells me that I posted below. If you don't need/ want them, just remove them in the parser.
I don't think you can use the parser you used in your example without having some form of extra fields like I showed in my previous answer, since those parsers usually go for property names as fields and I guess you don't want to create classes dynamically during runtime.
I also don't think that it is possible for you to create a dynamic depth of your parent-child-child-child...-relationship with Lists, Arrays or Dictionaries, because those structures have a set depth as soon as they are declared.
Class:
public class MyJsonObject
{
public List<string> Columns = new List<string>();
public string ChildName;
public List<MyJsonObject> Children = new List<MyJsonObject>();
}
Parser:
class JsonParser
{
public static string Parse(MyJsonObject jsonObject)
{
string parse = "{";
parse += string.Join(",", jsonObject.Columns.Select(column => $"\"{column}\": \"\""));
if (!string.IsNullOrEmpty(jsonObject.ChildName))
{
parse += $",\"{jsonObject.ChildName}\":";
parse += $"[{string.Join(",", jsonObject.Children.Select(Parse))}]";
}
parse += "}";
return parse;
}
}
Usage:
class Program
{
static void Main(string[] args)
{
MyJsonObject company = new MyJsonObject();
company.ChildName = "Department";
company.Columns.Add("Id");
company.Columns.Add("Name");
company.Columns.Add("Location");
MyJsonObject department = new MyJsonObject();
department.ChildName = "Employee";
department.Columns.Add("Id");
department.Columns.Add("Name");
department.Columns.Add("CompanyId");
MyJsonObject employee1 = new MyJsonObject();
employee1.Columns.Add("Id");
employee1.Columns.Add("Name");
employee1.Columns.Add("DepartmentId");
MyJsonObject employee2 = new MyJsonObject();
employee2.Columns.Add("Id");
employee2.Columns.Add("Name");
employee2.Columns.Add("DepartmentId");
company.Children.Add(department);
department.Children.Add(employee1);
department.Children.Add(employee2);
var json = JsonParser.Parse(company);
}
}
Output and Link to JSON-Validator:
https://jsonformatter.curiousconcept.com/
{
"Id":"",
"Name":"",
"Location":"",
"Department":[
{
"Id":"",
"Name":"",
"CompanyId":"",
"Employee":[
{
"Id":"",
"Name":"",
"DepartmentId":""
},
{
"Id":"",
"Name":"",
"DepartmentId":""
}
]
}
]
}
Perhaps I'm missing something. If you create the classes you need in the heirachy, instantiate them with data and then serialize them, the structure will be created for you.
using System.Web.Script.Serialization;
public class Employee
{
public int Id {get; set; }
public string Name {get; set; }
public int DepartmentId {get; set; }
}
public class Department
{
public int Id {get; set; }
public string Name {get; set; }
public string CompanyId {get; set; }
public List<Employee> {get; set;}
}
public class Company {
public int Id {get; set; }
public string Name {get; set; }
public string Location {get; set; }
public List<Department> {get; set;}
}
var myCompany = new Company();
// add departments and employees
var json = new JavaScriptSerializer().Serialize(myCompany);
You can use dynamic:
//here your database
dynamic[] company = new object[] { new { Name = "Company1", DepartmentId = 1 }, new { Name = "Company2", DepartmentId = 2 } };
dynamic[] department = new object[] { new { DepartmentId = 1, Name = "Department1" }, new { DepartmentId = 2, Name = "Department2" } };
//select from database
var data = from c in company
join d in department on c.DepartmentId equals d.DepartmentId
select new {Name = c.Name, Department = d};
var serialized = JsonConvert.SerializeObject(data);
result:
[
{
"Name": "Company1",
"Department": {
"DepartmentId": 1,
"Name": "Department1"
}
},
{
"Name": "Company2",
"Department": {
"DepartmentId": 2,
"Name": "Department2"
}
}
]
Ok, lets try like this. First of all as i understand your preblem: u have arrays of properties of parents and child and u neet to convert it to json object.
The point is here:
public static ExpandoObject DicTobj(Dictionary<string, object> properties)
{
var eo = new ExpandoObject();
var eoColl = (ICollection<KeyValuePair<string, object>>)eo;
foreach (var childColumn in properties)
eoColl.Add(childColumn);
return eo;
}
U use dynamic and ExpandoObject to convert dictionary to object
The other code is trivial: u put all your objects to one using dynamic type
and serialize it.
The full code:
public static Child Child1 { get; set; } = new Child
{
Name = "Child1"
};
public static Parent Parent1 { get; set; } = new Parent
{
Name = "Parent1"
};
public static Parent Parent2 { get; set; } = new Parent
{
Name = "Parent2"
};
private static void Main(string[] args)
{
var result = GetData(Child1, new List<Parent> {Parent1, Parent2});
Console.WriteLine(result);
}
/// <summary>
/// This is the magic: convert dictionary of properties to object with preperties
/// </summary>
public static ExpandoObject DicTobj(Dictionary<string, object> properties)
{
var eo = new ExpandoObject();
var eoColl = (ICollection<KeyValuePair<string, object>>) eo;
foreach (var childColumn in properties)
eoColl.Add(childColumn);
return eo;
}
public static string GetData(Child model, List<Parent> parents)
{
var childColumns = GetColumns(model);
dynamic child = DicTobj(childColumns);
var parentsList = new List<object>();
foreach (var parent in parents)
{
var parentColumns = GetColumns(parent);
var parentObj = DicTobj(parentColumns);
parentsList.Add(parentObj);
}
child.Parents = parentsList;
return JsonConvert.SerializeObject(child);
}
/// <summary>
/// this is STUB method for example
/// I change return type from string[] to Dictionary[columnName,ColumnValue], becouse u need not only column names, but
/// with it values, i gues. If not, look commented example at the end of this method
/// </summary>
public static Dictionary<string, object> GetColumns(object model)
{
var result = new Dictionary<string, object>();
if (model == Child1)
{
result.Add("Id", "1");
result.Add("Name", "Child1");
result.Add("Location", "SomeLocation");
}
if (model == Parent1)
{
result.Add("Id", "2");
result.Add("Name", "Parent1");
result.Add("SomeProperty1", "SomeValue1");
}
if (model == Parent2)
{
result.Add("Id", "3");
result.Add("Name", "Parent1");
result.Add("SomeProperty3", "SomeValue2");
}
//if u have only columNames and dont need values u can do like this
//var columns = new[] {"Id", "Name", "SomeProperty1"};//this u get from DB
//return columns.ToDictionary(c => c, c => new object());
return result;
}
}
public class Child
{
public string Name { get; set; } // Contains Employee
//Other properties and info related to process sql query and connection string
}
public class Parent
{
public string Name { get; set; } // Contains Company,Department.
public string SqlQuery { get; set; } // query related to Company and Department.
//Other properties and info related to connection string
}
And result output:
{
"Id": "1",
"Name": "Child1",
"Location": "SomeLocation",
"Parents": [
{
"Id": "2",
"Name": "Parent1",
"SomeProperty1": "SomeValue1"
},
{
"Id": "3",
"Name": "Parent1",
"SomeProperty3": "SomeValue2"
}
]
}
You can pass any kind of object even if you don't have a fixed structure:
Newtonsoft.Json.JsonConvert.SerializeObject(new yourCustomObject)
By using this.
The best way to to get this result
- You have to create a new class which has the relation of all the class. Then use the
Newtonsoft.Json.JsonConvert.SerializeObject(new organization )
Let creates a new class named organization . Add the relation which you want to see in Json. Then convert into the JSON using JsonConvert.
Or you can use the following dynamic loop
//here your database<br/>
dynamic[] company = new object[] { new { Name = "Company1", DepartmentId = 1 }, new { Name = "Company2", DepartmentId = 2 } };
dynamic[] department = new object[] { new { DepartmentId = 1, Name = "Department1" }, new { DepartmentId = 2, Name = "Department2" } };
//select from database<br/>
var data = from c in company
join d in department on c.DepartmentId equals d.DepartmentId
select new {Name = c.Name, Department = d};
var serialized = JsonConvert.SerializeObject(data);
I have a list in this table
public class Fruits
{
public int ID { get; set; }
public string Name{ get; set; }
}
I want to know what are the most frequent fruit in this table what is the code that appears to me this result
I am use
var max = db.Fruits.Max();
There is an error in that?
Try
public class Fruits
{
public int ID { get; set; }
public string Name{ get; set; }
}
var Val = fruitList.GroupBy(x => x.ID,
(key, y) => y.MaxBy(x => x.ID).value)
As Drew said in the comments, you want to GroupBy on the value that you care about (I did Name, since ID tends to be unique in most data structures) and then OrderByDescending based on the count.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var fruits = new List<Fruit> { new Fruit { ID = 1, Name = "Apple" }, new Fruit { ID = 2, Name = "Apple" }, new Fruit { ID = 3, Name = "Pear" } };
var most = fruits.GroupBy(f => f.Name).OrderByDescending(group => group.Count());
Console.WriteLine(most.First().Key);
}
}
public class Fruit
{
public int ID { get; set; }
public string Name{ get; set; }
}
If you want to get the name of the item that exists most in your list, first find the id that is most occurring:
var fruitAnon = fruits
.GroupBy(item => item.ID)
.Select(item => new {
Key = item.Key,
Count = item.Count()
})
.OrderByDescending(item => item.Count)
.FirstOrDefault();
This will return an anonymous object that will have the most frequent id, and the count represents the number of times it exists in the list. You can then find that object's name:
var fruit = fruits.FirstOrDefault(x => x.ID == fruitAnon.Key);
If you had a list like this:
List<Fruits> fruits = new List<Fruits>() {
new Fruits { ID = 1, Name = "Apple" },
new Fruits { ID = 1, Name = "Apple" },
new Fruits { ID = 2, Name = "Orange" },
new Fruits { ID = 2, Name = "Orange" },
new Fruits { ID = 2, Name = "Orange" },
new Fruits { ID = 2, Name = "Orange" }
};
Then:
Console.WriteLine(fruit.Name);
Would print Orange.