Merge and map from one class to another in C# using linq - c#

I have a list of class like the below,
{
"Id": "ABCD",
"location": "ABCD Location",
"TypeId": "Mango",
"free": 3,
"total": 6
},
{
"locationId": "ABCD",
"location": "ABCD Location",
"deviceTypeId": "Apple",
"free": 4,
"total": 8
}
I want to map it to another class as below.
{
"locationId": "ABCD",
"location": "ABCD Location",
"Fruits":
{
Fruit:
{
TypeId: "Mango",
Free:"3",
Total: "6"
}
Fruit:
{
TypeId: "Apple",
Free:"4",
Total: "8"
}
}
}
How do I do merge and map the first class to another class using linq in c#?

You need something like below:
class Program
{
static void Main(string[] args)
{
List<class1> data = new List<class1>
{
new class1
{
Id= "ABCD",
location = "ABCD Location",
TypeId="Mango",
free=3,
total=6
},
new class1
{
Id="ABCD",
location="ABCD Location",
TypeId="Apple",
free=4,
total=8
}
};
var result = data.GroupBy(g => new
{
locationId = g.Id,
location = g.location
}).Select(s => new class2
{
locationId=s.Key.locationId,
location=s.Key.location,
Fruits=s.Select(f=>new Fruits
{
Free=f.free,
Total=f.total,
TypeId=f.TypeId
}).ToList()
}).ToList();
Console.ReadLine();
}
public class class1
{
public string Id { get; set; }
public string location { get; set; }
public string TypeId { get; set; }
public int free { get; set; }
public int total { get; set; }
}
public class class2
{
public string locationId { get; set; }
public string location { get; set; }
public string deviceTypeId { get; set; }
public List<Fruits> Fruits { get; set; }
}
public class Fruits
{
public string TypeId { get; set; }
public int Free { get; set; }
public int Total { get; set; }
}
}

Related

How can i improve filter on JSON?

As a title, i'm trying to access some child by following solution from this thread C# JSON.Net parse and get list of all elements matching a value using LINQ .
Here is my code
var result = await response.Content.ReadAsStringAsync();
var jsonData = (JObject)JsonConvert.DeserializeObject(result);
var doc = (JContainer)jsonData["symbols"];
var results = doc.Descendants()
.OfType<JObject>()
.Where(x => x["filterType"] != null &&
x["filterType"].Value<string>() == "MARKET_LOT_SIZE").ToList();
Result is pretty good so far, Here is sample result what i get from trial and error
{
"stepSize": "0.001",
"filterType": "MARKET_LOT_SIZE",
"maxQty": "120",
"minQty": "0.001"
},
{
"stepSize": "0.001",
"filterType": "MARKET_LOT_SIZE",
"maxQty": "140",
"minQty": "0.002"
}
It turn out that result is skip a lot of child to check, but that's not what i expected
i still expect to check upper child to make sure i access child correctly.
Here is real response
{
"timezone": "UTC",
"serverTime": 1660492828507,
"futuresType": "U_MARGINED",
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 2400
},
{
"rateLimitType": "ORDERS",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 1200
},
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 300
}
],
"exchangeFilters": [],
"assets": [
{
"asset": "USDT",
"marginAvailable": true,
"autoAssetExchange": "-10000"
},
{
"asset": "BTC",
"marginAvailable": true,
"autoAssetExchange": "-0.00100000"
},
{
"asset": "BNB",
"marginAvailable": true,
"autoAssetExchange": "-10"
},
{
"asset": "ETH",
"marginAvailable": true,
"autoAssetExchange": "-5"
},
{
"asset": "XRP",
"marginAvailable": true,
"autoAssetExchange": "0"
},
{
"asset": "ADA",
"marginAvailable": true,
"autoAssetExchange": "0"
},
{
"asset": "USDC",
"marginAvailable": true,
"autoAssetExchange": "-10000"
},
{
"asset": "DOT",
"marginAvailable": true,
"autoAssetExchange": "0"
},
{
"asset": "SOL",
"marginAvailable": true,
"autoAssetExchange": "0"
},
{
"asset": "BUSD",
"marginAvailable": true,
"autoAssetExchange": "-10000"
}
],
"symbols": [
{
"symbol": "BTCUSDT",
"pair": "BTCUSDT",
"contractType": "PERPETUAL",
"deliveryDate": 4133404800000,
"onboardDate": 1569398400000,
"status": "TRADING",
"maintMarginPercent": "2.5000",
"requiredMarginPercent": "5.0000",
"baseAsset": "BTC",
"quoteAsset": "USDT",
"marginAsset": "USDT",
"pricePrecision": 2,
"quantityPrecision": 3,
"baseAssetPrecision": 8,
"quotePrecision": 8,
"underlyingType": "COIN",
"underlyingSubType": [
"PoW"
],
"settlePlan": 0,
"triggerProtect": "0.0500",
"liquidationFee": "0.015000",
"marketTakeBound": "0.05",
"filters": [
{
"minPrice": "556.80",
"maxPrice": "4529764",
"filterType": "PRICE_FILTER",
"tickSize": "0.10"
},
{
"stepSize": "0.001",
"filterType": "LOT_SIZE",
"maxQty": "1000",
"minQty": "0.001"
},
{
"stepSize": "0.001",
"filterType": "MARKET_LOT_SIZE",
"maxQty": "120",
"minQty": "0.001"
},
{
"limit": 200,
"filterType": "MAX_NUM_ORDERS"
},
{
"limit": 10,
"filterType": "MAX_NUM_ALGO_ORDERS"
},
{
"notional": "5",
"filterType": "MIN_NOTIONAL"
},
{
"multiplierDown": "0.9500",
"multiplierUp": "1.0500",
"multiplierDecimal": "4",
"filterType": "PERCENT_PRICE"
}
],
"orderTypes": [
"LIMIT",
"MARKET",
"STOP",
"STOP_MARKET",
"TAKE_PROFIT",
"TAKE_PROFIT_MARKET",
"TRAILING_STOP_MARKET"
],
"timeInForce": [
"GTC",
"IOC",
"FOK",
"GTX"
]
},
{
"symbol": "ETHUSDT",
"pair": "ETHUSDT",
"contractType": "PERPETUAL",
"deliveryDate": 4133404800000,
"onboardDate": 1569398400000,
"status": "TRADING",
"maintMarginPercent": "2.5000",
"requiredMarginPercent": "5.0000",
"baseAsset": "ETH",
"quoteAsset": "USDT",
"marginAsset": "USDT",
"pricePrecision": 2,
"quantityPrecision": 3,
"baseAssetPrecision": 8,
"quotePrecision": 8,
"underlyingType": "COIN",
"underlyingSubType": [
"Layer-1"
],
"settlePlan": 0,
"triggerProtect": "0.0500",
"liquidationFee": "0.015000",
"marketTakeBound": "0.05",
"filters": [
{
"minPrice": "39.86",
"maxPrice": "306177",
"filterType": "PRICE_FILTER",
"tickSize": "0.01"
},
{
"stepSize": "0.001",
"filterType": "LOT_SIZE",
"maxQty": "10000",
"minQty": "0.001"
},
{
"stepSize": "0.001",
"filterType": "MARKET_LOT_SIZE",
"maxQty": "2000",
"minQty": "0.001"
},
{
"limit": 200,
"filterType": "MAX_NUM_ORDERS"
},
{
"limit": 10,
"filterType": "MAX_NUM_ALGO_ORDERS"
},
{
"notional": "5",
"filterType": "MIN_NOTIONAL"
},
{
"multiplierDown": "0.9500",
"multiplierUp": "1.0500",
"multiplierDecimal": "4",
"filterType": "PERCENT_PRICE"
}
],
"orderTypes": [
"LIMIT",
"MARKET",
"STOP",
"STOP_MARKET",
"TAKE_PROFIT",
"TAKE_PROFIT_MARKET",
"TRAILING_STOP_MARKET"
],
"timeInForce": [
"GTC",
"IOC",
"FOK",
"GTX"
]
}
]
}
I want to get maxQty of MARKET_LOT_SIZE where symbol is BTCUSDT and contractType is PERPETUAL. What should i add more filter on this
For your requirement I suggest to create a class and use LINQ on top of that. This will help you in adding conditions quickly
Step1: use json2csharp to convert the json to C# Model
Step2:DeserializeObject using Newtonsoft.JsonConvert
Step3: Add LINQ to get desired output
//STEP2
var doc = JsonConvert.DeserializeObject<Root>(jsonData);
//STEP3
var maxQty = doc.symbols.Where(s => s.symbol == "BTCUSDT" && s.contractType == "PERPETUAL")
.SelectMany(x => x.filters)
.Where(y => y.filterType == "MARKET_LOT_SIZE")
.Max(x => x.maxQty);
//STEP1
public class Asset
{
public string asset { get; set; }
public bool marginAvailable { get; set; }
public string autoAssetExchange { get; set; }
}
public class Filter
{
public string minPrice { get; set; }
public string maxPrice { get; set; }
public string filterType { get; set; }
public string tickSize { get; set; }
public string stepSize { get; set; }
public string maxQty { get; set; }
public string minQty { get; set; }
public int? limit { get; set; }
public string notional { get; set; }
public string multiplierDown { get; set; }
public string multiplierUp { get; set; }
public string multiplierDecimal { get; set; }
}
public class RateLimit
{
public string rateLimitType { get; set; }
public string interval { get; set; }
public int intervalNum { get; set; }
public int limit { get; set; }
}
public class Root
{
public string timezone { get; set; }
public long serverTime { get; set; }
public string futuresType { get; set; }
public List<RateLimit> rateLimits { get; set; }
public List<object> exchangeFilters { get; set; }
public List<Asset> assets { get; set; }
public List<Symbol> symbols { get; set; }
}
public class Symbol
{
public string symbol { get; set; }
public string pair { get; set; }
public string contractType { get; set; }
public object deliveryDate { get; set; }
public object onboardDate { get; set; }
public string status { get; set; }
public string maintMarginPercent { get; set; }
public string requiredMarginPercent { get; set; }
public string baseAsset { get; set; }
public string quoteAsset { get; set; }
public string marginAsset { get; set; }
public int pricePrecision { get; set; }
public int quantityPrecision { get; set; }
public int baseAssetPrecision { get; set; }
public int quotePrecision { get; set; }
public string underlyingType { get; set; }
public List<string> underlyingSubType { get; set; }
public int settlePlan { get; set; }
public string triggerProtect { get; set; }
public string liquidationFee { get; set; }
public string marketTakeBound { get; set; }
public List<Filter> filters { get; set; }
public List<string> orderTypes { get; set; }
public List<string> timeInForce { get; set; }
}

c# Json get all parent and child values

I have a json string.
There are multiple subcategories within the json string depending on the category.
I want to combine them all.
It should always give the Id of the last child level of a higher level.
Sample :
Id - Name
-- ----------
1239 - Accessory> Jewelery > wristband> Silver wristband
Can anyone help me . Thanks
{
"categories": [
{
"id": 368,
**"name": "Accessory ",**
"parentId": null,
"subCategories": [
{
"id": 396,
**"name": "Jewelery ",**
"parentId": 368,
"subCategories": [
{
"id": 397,
**"name": "wristband",**
"parentId": 396,
"subCategories": [
{
"id": 1238,
"name": "Gold wristband",
"parentId": 397,
"subCategories": []
},
{
**"id": 1239,**
"name": "Silver wristband",
"parentId": 397,
"subCategories": []
},
{
"id": 2845,
"name": "Steel wristband",
"parentId": 397,
"subCategories": []
},
{
"id": 3171,
"name": "Pearl wristband",
"parentId": 397,
"subCategories": []
},
{
"id": 3883,
"name": "diamond wristband",
"parentId": 397,
"subCategories": []
}
]
}
]
}
]
}
]
}
Here my class
public class SubCategory
{
public int id { get; set; }
public string name { get; set; }
public int parentId { get; set; }
public List<object> subCategories { get; set; }
}
public class Category
{
public int id { get; set; }
public string name { get; set; }
public object parentId { get; set; }
public List<SubCategory> subCategories { get; set; }
}
public class Root
{
public List<Category> categories { get; set; }
}
I think you can drop SubCategory, what is that List<object> doing there anyway?
Assuming you can deserialize
public class Category
{
public int id { get; set; }
public string name { get; set; }
public int? parentId { get; set; } // int?
public List<Category> subCategories { get; set; } // <Category>
}
public class Root
{
public List<Category> categories { get; set; }
}
then you can use a simple depth-first recursive visitor:
string FindCategoryTrail(List<Category> categories, int id)
{
foreach(var category in categories)
{
if (category.id == id) return category.name;
var trail = FindCategoryTrail(category.subCategories , id);
if (trail != null)
{
return category.name + " > " + trail;
}
}
return null;
}
and call it like
string trail = FindCategoryTrail(myRoot.categories, 1239);
using Linq, you could flatten the nested lists:
public class Category
{
public int id { get; set; }
public string name { get; set; }
public object parentId { get; set; }
public List<Category> subCategories { get; set; }
}
public class Root
{
public List<Category> categories { get; set; }
}
IEnumerable<Category> Flatten(IEnumerable<Category> e) => e.SelectMany(c => Flatten(c.subCategories)).Concat(e);
Root root = JsonConvert.DeserializeObject<Root>(File.ReadAllText(#"U:\test1.json"));
var search = Flatten(root.categories).Where(c => c.id == 1239);
foreach(var s in search)
{
System.Diagnostics.Debug.WriteLine($"id: {s.id}");
System.Diagnostics.Debug.WriteLine($"name: {s.name}");
System.Diagnostics.Debug.WriteLine($"parentid: {s.parentId}");
}

Flattening complex data into a single object

I am trying to abstract data from a complex and create a EventDto.
And I was able to do it using foreach but the syntax is dreadful.
Is there a better way of writing this code?
public class EventDtO
{
public string Id { get; set; }
public string Title { get; set; }
public string CategoryTitle { get; set; }
public DateTime DateTime { get; set; }
}
This is the complex object that i am trying to get the data from
public class RootObject
{
public List<Event> Events { get; set; }
}
public class Event
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Link { get; set; }
public List<Category> Categories { get; set; }
public List<Geometry> Geometries { get; set; }
}
public class Geometry
{
public DateTime Date { get; set; }
public string Type { get; set; }
public List<object> Coordinates { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Title { get; set; }
}
The mapping relationship i want is
EventDto.Id->Event.Id
EventDto.Title->Event.Title
Event.CategoryTitle->Category.Title
Event.DateTime->Geometry.Date
The Category class will only contain one value, but the geometry.Date can have multiple values.
So the output i want is:
Title Categories Date
"Iceberg B42" Sea and Lake Ice 2020-04-23T14:24:00Z
"Iceberg B42" Sea and Lake Ice 2017-09-15T00:00:00Z
I am able to get the correct information if i do the following code.
var Event = new List<EventDTO>();
foreach (var con in content.Events)
{
var data = new EventDTO
{
Title = con.Title,
Id = con.Id
};
foreach (var cat in con.Categories)
{
data.CategoriesTitle = cat.Title;
}
foreach (var geo in con.Geometries)
{
data.DateTime = geo.Date;
Event.Add(data);
}
}
An example of the json
{
"id": "EONET_2881",
"title": "Iceberg B42",
"description": "",
"categories": [
{
"id": 15,
"title": "Sea and Lake Ice"
}
]
"geometries": [
{
"date": "2017-04-21T00:00:00Z",
"type": "Point",
"coordinates": [ -107.19, -74.63 ]
},
{
"date": "2017-09-15T00:00:00Z",
"type": "Point",
"coordinates": [ -107.11, -74.08 ]
}
]
}
You weren't creating a new EventDTO for each Geometry. Wouldn't this lead to multiple records with the date of the last one? Is this what you are looking for;
var Event = content.Events.SelectMany(con =>
con.Geometries.Select(geo =>
new EventDTO
{
Title = con.Title,
Id = con.Id,
CategoriesTitle = con.Categories.FirstOrDefault().Title,
DateTime = geo.Date
})
).ToList();

EF Core stop recursion on theninclude

I am using .NET Core 3 with the latest Entity Framework Core. I currently have 3 tables, two normal tables and one linking table. They are structured below. I am trying to get the accessory by itself for the vehicle it is linked to, what currently is happening is that it recurses back into itself and loads the vehicle object again (since it has a reference to the linking table). Does anyone know how I can stop this recursion from taking place? I don't want the VehicleAccessory to have the vehicleAccessories array within it, that is causing the recursion.
Call
var result = _context.Vehicles
.Include(x => x.VehicleAccessories)
.ThenInclude(x => x.Accessory)
.Include(x => x.VehicleImages)
.ThenInclude(x => x.Image)
.ToList();
return result;
Call result
{
"id": 1,
"registrationNumber": "123456",
"make": "BMW",
"model": "M3",
"year": 2009,
"kilometers": 10030,
"vehicleIdentificationNumber": "1234567890",
"retailPrice": 100000.00,
"costPrice": 50000.00,
"vehicleAccessories": [
{
"vehicleId": 1,
"accessoryId": 1,
"accessory": {
"id": 1,
"description": "NEW ONE",
"vehicleAccessories": []
}
},
{
"vehicleId": 1,
"accessoryId": 2,
"accessory": {
"id": 2,
"description": "NEW ONE",
"vehicleAccessories": [
{
"vehicleId": 2,
"vehicle": {
"id": 2,
"registrationNumber": "123456",
"make": "BMW",
"model": "M3",
"year": 2009,
"kilometers": 10030,
"vehicleIdentificationNumber": "1234567890",
"retailPrice": 100000.00,
"costPrice": 50000.00,
"vehicleAccessories": [],
"vehicleImages": [],
"dtCreated": "2020-02-03T11:21:48.2245986",
"dtUpdated": "2020-02-03T11:21:48.2245554"
},
"accessoryId": 2
}
]
}
}
],
"vehicleImages": [],
"dtCreated": "2020-02-03T11:20:13.8890848",
"dtUpdated": "2020-02-03T11:20:13.8890488"
}
Vehicle table:
public class Vehicle
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string RegistrationNumber { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public int Kilometers { get; set; }
public string VehicleIdentificationNumber { get; set; }
public decimal RetailPrice { get; set; }
public decimal CostPrice { get; set; }
public ICollection<VehicleAccessory> VehicleAccessories { get; } = new List<VehicleAccessory>();
public ICollection<VehicleImage> VehicleImages { get; set; }
public DateTime DTCreated { get; set; }
public DateTime DTUpdated { get; set; }
}
Accessory Table
public class Accessory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string Description { get; set; }
public ICollection<VehicleAccessory> VehicleAccessories { get; } = new List<VehicleAccessory>();
}
Linking Table
public class VehicleAccessory
{
public long VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
public long AccessoryId { get; set; }
public Accessory Accessory { get; set; }
}
Relationship in context
builder.Entity<VehicleAccessory>()
.HasKey(t => new { t.AccessoryId, t.VehicleId });

json.net deserialization return null

I'm trying to deserialize a JSON string into a C# object. When I trap in the debugger, the JSON visualizer appears to be parsing the string just fine. However, when I push the string through the following code, the object returned has null values for the properties.
Here's my code:
public static Item GetPrices(string itemStr)
{
Item item = JsonConvert.DeserializeObject<Item>(itemStr);
return item;
}
public class Item
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "prices")]
public Prices Prices { get; set; }
}
public class Prices
{
[JsonProperty(PropertyName = "priceUofM")]
public PriceUofM[] PriceUofMs { get; set; }
}
public class PriceUofM
{
[JsonProperty(PropertyName = "uofm")]
public string UofM { get; set; }
[JsonProperty(PropertyName = "price")]
public string Price { get; set; }
}
and here's what I'm passing to it:
{
"item": {
"id": "1A50CC070S",
"prices":
[
{
"priceUofM": {
"uofm": "BOX",
"price": "$81.11"
}
},
{
"priceUofM": {
"uofm": "CASE",
"price": "$811.11"
}
}
]
}
}
I've run it through several online parsers, and all of them appear to be interpreting the JSON string just fine. What am I doing wrong in formatting the string to cause JsonConvert.DeserializeObject to fail?
Given this json:
{
"item": {
"id": "1A50CC070S",
"prices":
[
{
"priceUofM": {
"uofm": "BOX",
"price": "$81.11"
}
},
{
"priceUofM": {
"uofm": "CASE",
"price": "$811.11"
}
}
]
}
}
C# model would be:
public class Model
{
[JsonProperty("item")]
public Item Item { get; set; }
}
public class Item
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("prices")]
public List<Price> Prices { get; set; }
}
public class Price
{
[JsonProperty("priceUofM")]
public PriceUofM PriceUofM { get; set; }
}
public class PriceUofM
{
[JsonProperty("uofm")]
public string UofM { get; set; }
[JsonProperty("price")]
public string Price { get; set; }
}
In order to deserialize the string into an Item object, JSON string would be something like:
{
"id": "1A50CC070S",
"prices":
[
{
"priceUofM": {
"uofm": "BOX",
"price": "$81.11"
}
},
{
"priceUofM": {
"uofm": "CASE",
"price": "$811.11"
}
}
]
}

Categories

Resources