I've been trying to deserialize a Json string that contains a list of ints representing colors to then be inserted into a sql database using Entity Framework. I'm pretty new to Entity Framework and read that it doesn't support collections of primitive types, I thought to get around it I could add the class
public class Colors
{
public int Id { get; set; }
public int Color { get; set; }
}
and then create a list in the CharacterColor class to hold the ints
public List<Colors> Colors { get; set; }
However I get the error when trying to deserialize the Json.
Newtonsoft.Json.JsonSerializationException: 'Error converting value
255 to type 'ORAC.Data.Entities.Colors'. Path
'characterColors[0].colors[0]', line 1, position 1200.'
ArgumentException: Could not cast or convert from System.Int64 to ORAC.Data.Entities.Colors.
Would anyone with more experience with Entity Framework be able to see where I'm going wrong.
Character character = JsonConvert.DeserializeObject<Character>(jsonString);
Json string
"{\"packedRecipeType\":\"DynamicCharacterAvatar\",\"name\":\"Character\",\"race\":\"HumanMaleHighPoly\",\"dna\":[{\"dnaType\":\"UMADnaHumanoid\",\"dnaTypeHash\":-212795365,\"packedDna\":\"{\\\"height\\\":128,\\\"headSize\\\":128,\\\"headWidth\\\":93,\\\"neckThickness\\\":108,\\\"armLength\\\":135,\\\"forearmLength\\\":128,\\\"armWidth\\\":116,\\\"forearmWidth\\\":128,\\\"handsSize\\\":118,\\\"feetSize\\\":109,\\\"legSeparation\\\":128,\\\"upperMuscle\\\":129,\\\"lowerMuscle\\\":152,\\\"upperWeight\\\":128,\\\"lowerWeight\\\":81,\\\"legsSize\\\":134,\\\"belly\\\":66,\\\"waist\\\":108,\\\"gluteusSize\\\":38,\\\"earsSize\\\":121,\\\"earsPosition\\\":233,\\\"earsRotation\\\":61,\\\"noseSize\\\":115,\\\"noseCurve\\\":128,\\\"noseWidth\\\":124,\\\"noseInclination\\\":128,\\\"nosePosition\\\":128,\\\"nosePronounced\\\":128,\\\"noseFlatten\\\":118,\\\"chinSize\\\":128,\\\"chinPronounced\\\":128,\\\"chinPosition\\\":128,\\\"mandibleSize\\\":128,\\\"jawsSize\\\":128,\\\"jawsPosition\\\":128,\\\"cheekSize\\\":128,\\\"cheekPosition\\\":128,\\\"lowCheekPronounced\\\":128,\\\"lowCheekPosition\\\":195,\\\"foreheadSize\\\":128,\\\"foreheadPosition\\\":128,\\\"lipsSize\\\":128,\\\"mouthSize\\\":128,\\\"eyeRotation\\\":128,\\\"eyeSize\\\":69,\\\"breastSize\\\":128}\"},{\"dnaType\":\"UMADnaTutorial\",\"dnaTypeHash\":-1679007774,\"packedDna\":\"{\\\"eyeSpacing\\\":128}\"}],\"characterColors\":[{\"name\":\"Skin\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Hair\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Eyes\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Undies\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]}],\"wardrobeSet\":[{\"slot\":\"Underwear\",\"recipe\":\"MaleUnderwear\"}],\"raceAnimatorController\":\"Locomotion\"}"
Entity
public class Character
{
public int UserId { get; set; }
public int CharacterId { get; set; }
public string CharacterName { get; set; }
public string PackedRecipeType { get; set; }
public string Name { get; set; }
public string Race { get; set; }
public List<Dna> Dna { get; set; }
public List<CharacterColor> CharacterColors { get; set; }
public List<WardrobeSet> WardrobeSet { get; set; }
public string RaceAnimatorController { get; set; }
public User User { get; set; }
}
public class Dna
{
public int Id { get; set; }
public string DnaType { get; set; }
public int DnaTypeHash { get; set; }
public string PackedDna { get; set; }
}
public class CharacterColor
{
public int Id { get; set; }
public string Name { get; set; }
public List<Colors> Colors { get; set; }
}
public class WardrobeSet
{
public int Id { get; set; }
public string Slot { get; set; }
public string Recipe { get; set; }
}
public class Colors
{
public int Id { get; set; }
public int Color { get; set; }
}
Solution
I updated the Json and replaced the colors array with a new array of objects
JObject jsonToParse = JObject.Parse(jsonString);
JArray characterColors = (JArray)jsonToParse["characterColors"];
foreach(var item in characterColors)
{
JArray colors = (JArray)item["colors"];
JArray newColorsArray = new JArray();
var i = 0;
foreach (var col in colors)
{
var color = new Color
{
ColorId = i,
Value = (int)col
};
newColorsArray.Add(JToken.FromObject(color));
i++;
}
colors.Replace(newColorsArray);
}
In your Json you have colors defined as an array of ints, not as an object array of your new Colors class. Should be more like colors: [{Id:0, Color:255},{Id:2, Color:255}, .......]
So the JSON is incorrect, in the json the colors array is sent as a List basically
colors: [255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]
but the .net is expecting something more like the following which is more like a List
colors: [{Id:0, Color:255},{Id:1, Color:255}, ...]
So you can do any of the following:
Change whatever is sending your JSON to send an array of objects of {int, int} instead of an array of ints.
Change your List to be a List and then update all your .net code to adjust to that.
Write a custom Json converter to convert from the json you have to the .net that you have.
You should do 1 or 2, as your data doesn't seem complex enough to go through the effort of 3.
How can I compare to array in linq and get all elements where there is at least one intersection?
Example:
selectes = {1,5,7}
Bands[0].SongsID {1,9}
Bands[1].SongsID {5,6}
Bands[2].SongsID {4,6}
I need to select Bands[0] and Bands[1].
I tried this:
var selectes2 = Bands.Where(t => t.SongsID.Intersect(selectes));
Bands class:
public class Band
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime YearOfCreate { get; set; }
public string Country { get; set; }
public int[] SongsID { get; set; }
}
var selectes2 = Bands.Where(t => t.SongsID.Intersect(selectes).Any());
Assuming you mean to select any band that has any song ID that matches your list of ids, you could accomplish that with this:
var matchingBands = Bands.Where(band => band.SongsID.Any(selectes.Contains));
I have two tables "CategoryGroup" and "Category" which returns data in one list. Requirement is to convert flat list to hierarchy list like CategoryGroup contains related categories.
Please suggest how to convert into hieararchy list?
public class ProfileConditionGroup
{
public Guid ConditionGroupGUID { get; set; }
public string ConditionGroupName { get; set; }
public List<ProfileConditionList> profileConditions { get; set; }
}
public class ProfileConditionList
{
public string ConditionName { get; set; }
public Nullable<Guid> ConditionGUID { get; set; }
public string[] ThisConditionSelectedByProfileIDs { get; set; }
public Nullable<Guid> ParentConditionGroupGUID { get; set; }
public bool IsDefaultSelected { get; set; }
}
This is actually a little tricky without having an actual concrete return type, but here's the way I'd tackle it if you're just building a tree of Guid values.
Given this query:
var query =
from pcg in pcgs
from pcl in pcg.profileConditions
select new
{
pcg.ConditionGroupName,
pcg.ConditionGroupGUID,
pcl.ConditionName,
pcl.ConditionGUID,
pcl.ThisConditionSelectedByProfileIDs,
pcl.ParentConditionGroupGUID,
pcl.IsDefaultSelected,
};
...I'd do this:
var lookup = query.ToLookup(x => x.ParentConditionGroupGUID);
Func<Guid?, Tree<Guid?>> build = null;
build = g =>
{
var r = new Tree<Guid?>() { Value = g };
r.AddRange(lookup[g].Select(x => build(x.ConditionGroupGUID)));
return r;
};
Now you just call build(null) and you should get a tree of Guid?. If you can create you're own output class you'd change the function to Func<Guid?, Tree<YourOutputClass>>.
You need this class for the tree:
public class Tree<T> : List<Tree<T>>
{
public T Value { get; set; }
}
I have a List<> which contains collection of objects after getting this list of BillSheetDetail I want to find that billWorkDetails[].details_classification =="xyz" and if it is found then fetch all the data of that particular array index of billWorksDetails[] and store it in other array to display.
How can I do this? I am new to C#
public class BillSheetDetail
{
public DateTime creation_date { get; set; }
public string customer_name { get; set; }
public string subject { get; set; }
public decimal tax_rate { get; set; }
public int total_amount { get; set; }
public string special_instruction { get; set; }
public string comment { get; set; }
public List<BillWorkDetail> billWorkDetails { get; set; }
}
[Serializable]
public class BillWorkDetail
{
public string product_name { get; set; }
public decimal quantity { get; set; }
public string unit { get; set; }
public int unit_cost { get; set; }
public int amount { get; set; }
public string remarks { get; set; }
public int row_no { get; set; }
public string details_classifiction { get; set; }
}
You have to combine Enumerable.Where and Any.
List<BillWorkDetail>[] matchingSheetDetails = billSheetDetailList
.Where(sd => sd.billWorkDetails.Any(d => d.details_classifiction == "xyz"))
.Select(sd => sd.billWorkDetails)
.ToArray();
This creates an array of all matching lists. Since your question is unclear, if you actually only want an array of the matching BillWorkDetail objects:
BillWorkDetail[] matchingBillWorkDetails = billSheetDetailList
.SelectMany(sd => sd.billWorkDetails.Where(d => d.details_classifiction == "xyz"))
.ToArray();
SelectMany selects all matching BillWorkDetail out of the List<BillSheetDetail>. Note that both approaches lose the reference to the BillSheetDetail instance from where it came from.
The solution is using the Where clause:
mySheetDetail.billWorkDetails.Where(x => x.details_classification == "xyz").ToList();
Here is a demonstration of the code that is working well: http://ideone.com/s2cUaR
Try this linq method
List<BillWorkDetail> myBillWorkDetails = new Lis<BillWorkDetail>();
myBillWorkDetails = myBillSheetDetail.billWorkDetails.Where(b => b.classifiction == "xyz").ToList();
This code retrieve all BillWorkDetail with classification xyz.