C# Linq Convert Object Property to Array - c#

I have an object that I am converting to JSON to be consumed by Ember.js.
Currently I have some child objects that are fully expanded but ember expects
just an array of ids on the client side. How can I flatten the object out to
be a int[]
items = Mapper.Map<IList<Item>>(client.GetItems());
foreach (var item in items)
{
int[] choices = item.Choices.Select(x => x.Id).ToArray();
item.Choices = choices;
}
get an error about not being able to convert to type int[] from IList<Item>
how can I cast the property?
example current JSON I produce after serializing
{ "items": [
{
"id": 0,
"name": "Item0",
"description": "...",
"choices": [
{ "id": 0, "property": "somevalue" },
{ "id": 1, "property": "somevalue" },
]
},
{
"id": 1,
"name": "Item1",
"description": "...",
"choices": [
{ "id": 0, "property": "somevalue" },
{ "id": 1, "property": "somevalue" },
]
}
]}
The JSON I would like to produce
{ "items": [
{
"id": 0,
"name": "Item0",
"description": "...",
"choices": [0, 1]
},
{
"id": 1,
"name": "Item1",
"description": "...",
"choices": [0, 1]
}
]}

SelectMany flattens List of Lists and produces single List with all items.
items.SelectMany(x=>x.Choices.Select(y=>y.Id).ToArray()));

get an error about not being able to convert to type int[] from IList how can I cast the property?
You cannot cast one type to another. Instead you can create another property of type int[] in your class and use the LINQ statement in getter (with necessary validation checks).
public int[] ChoiceIDs
{
get {
return this.Choices.Select(x => x.Id).ToArray();
}
}

Related

Elasticsearch terms query problem for "text" or "keyword" type fields

"hits" : [
{
"id": 1,
"sampleArrayData": ["x"]
},
{
"id": 2,
"sampleArrayData": ["y"]
},
{
"id": 3,
"sampleArrayData": ["z"]
},
{
"id": 4,
"sampleArrayData": ["x", "y", "z"]
},
{
"id": 5,
"sampleArrayData": ["z", "w"]
}
]
It's a sample data of index.
I want to search this index by sampleArrayData field which includes one or more values I will give dynamically.
For example if want to search this index by ["x","y"] parameters. I must get data which includes "x", or "y" or both "x", "y". (First three records from this index).
We could do this by using terms query on the old elastic search versions like below.
{
"query": {
"bool": {
"must": [
{
"terms": {
"sampleArrayData": [ "x", "y"]
}
}
]
}
}
}
But we can not use terms query for "text" or "keyword" type fields on the elasticsearch current versions.
How can I dynamically search this index with unknown number of parameters on the C# NEST library?

Merge 3 different json arrays in one object

I have three different arrays which I want to merge them into a single object.
array 1 : [{"Id":1,"Number":"1234","Category":"Chocalte", "Status": "Error"}]
heatingissues: [{"myId":3,"Id":"5801"}]
problemissue: [{"myId":1,"Id":2,"Name":"Desktop"}]
I want result to be like this:
{
"Id": 3,
"Number": "1190042293",
"Category": "Chocalte",
"heatingissues": [
{
"myId": 3,
"id": "5801"
}
],
"problemissue": [
{
"myId": 1,
"name": "Desktop"
}
]
}
After deserializing all the arrays individually (respectively to the results and problemissueresults variables) I try:
var j = JsonConvert.SerializeObject(new{
results,
heatingissues= problemissueresults,
problemissue= problemissueresults
});
Which generates the following output:
{
"results": [
{
"id": 3,
"Number": "1190042293",
"category": "Chocalte"
}
],
"heatingissues": [
{
"myId": 3,
"id": "5801"
}
],
"problemissue": [
{
"myId": 1,
"name": "Desktop"
}
]
}
How can I avoid these results?
In this case, you need to declare explicitly the properties of the object you are serializing to match the format you want.
In words of the documentation for C# Anonymous Types:
If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them
So your result was being serialized as an array with a json key of the same name.
Try this:
var obj =
new
{
id = results[0].id,
number = results[0].number,
category = results[0].category,
heatingissues= problemissueresults,
problemissue= problemissueresults
};
var j = JsonConvert.SerializeObject(obj);
Newtonsoft json library support merging operation.
http://www.newtonsoft.com/json/help/html/MergeJson.htm

LINQ: get nested arrays based on a groupby?

Suppose I have this simple object definition:
public class Item
{
public int section { get; set; }
public string item { get; set; }
}
I have some data in a single-depth array. This is JSON, which would be converted to C# objects via Json.NET:
[
{
"section": 0,
"item": "Hello!"
},
{
"section": 1,
"item": "First Steps"
},
{
"section": 1,
"item": "How to Ask for Help"
},
{
"section": 2,
"item": "Your First Program"
},
{
"section": 2,
"item": "The Code"
},
{
"section": 2,
"item": "How It Works"
},
{
"section": 3,
"item": "Where To Go From Here"
}
]
Using Entity Framework or some other method, I have arrived at a simple list of these objects as stated above, contained within a var variable.
Now what I want to do is get the same list, but where each section is grouped as an array within the outer array. For example, the JSON of what I want looks like this:
[
[
{
"section": 0,
"item": "Hello!"
}
],
[
{
"section": 1,
"item": "First Steps"
},
{
"section": 1,
"item": "How to Ask for Help"
}
],
[
{
"section": 2,
"item": "Your First Program"
},
{
"section": 2,
"item": "The Code"
},
{
"section": 2,
"item": "How It Works"
}
],
[
{
"section": 3,
"item": "Where To Go From Here"
}
]
]
My initial thought was to do something with a LINQ query using the groupby statement but I don't think this is what I'm looking for - groupby seems to be analogous to the SQL version so it can only be used for aggregate operations.
The only other option I have found so far is to use a LINQ query to get a list of all of the sections:
var allSections = (from x in myData select x.section).Distinct();
...and then iterate through those IDs and manually build the array:
List<List<Item>> mainList = new List<List<Item>>();
foreach (int thisSection in allSections.ToArray())
{
List<Item> thisSectionsItems = (from x in myData where x.section == thisSection select x).ToList();
mainList.Add(thisSectionsItems);
}
return mainList;
This should result in a proper enumerable that I can feed into JSON.NET and get the expected result, but this seems inefficient.
Is there a more LINQ-ish, or at least more efficient, way to split the items into groups?
You can certainly achieve this with .GroupBy()
var grouped = items
.GroupBy(x => x.section) // group by section
.Select(x => x.ToArray()) // build the inner arrays
.ToArray(); // return collection of arrays as an array

How to get all values from JSON in c# 3.5 framework?

Below is my JSON response. I want to fetch orderid, caseid each filed one by one and their value.
"cases": [
{
"status": "DISMISSED",
"createdAt": "2015-09-18T08:56:04+0000",
"investigationId": 19246020,
"caseId": 19246020,
"score": 794.6295793608853,
"adjustedScore": 794.6295793608853,
"updatedAt": "2015-09-18T08:56:05+0000",
"headline": "Steven Rusk",
"orderId": "116588",
"orderDate": "",
"orderAmount": 425.0,
"associatedTeam": {
"teamName": "B2C Jewels",
"teamId": 4289
},
"reviewDisposition": null,
"uuid": "5821ed91-5f8f-4b51-bd63-a8834f2a95b3"
},
{
"status": "DISMISSED",
"createdAt": "2015-09-16T11:33:28+0000",
"investigationId": 19114061,
"caseId": 19114061,
"score": 241.65405995385285,
"adjustedScore": 241.65405995385285,
"updatedAt": "2015-09-18T19:07:51+0000",
"headline": "221.134.83.50",
"orderId": "101",
"orderDate": "2015-09-16T17:07:30+0000",
"orderAmount": 9.99,
"associatedTeam": {
"teamName": "B2C Jewels",
"teamId": 4289
},
"reviewDisposition": null,
"uuid": "301f2cfc-3b67-4fc0-bf83-19099c2ea4bf"
},
]
You will have to create a class named as cases and then you need to map your json to the List then you can iterate through the list hope it will work for you .
List<cases> = new JavaScriptSerializer().Deserialize<List<cases>>(your json string);
You can install Json.Net package from Nuget and then add this line of code in you project
var myList = Newtonsoft.Json.JsonConvert.DeserializeObject("Your Json String..!!");
this should do it

JSON C# Parsing Error

This is my JSON
{
"3659639": {
"EventID": 3659639,
"RaceNum": 2,
"Meeting": "Newton Abbot",
"RaceType": "T",
"Description": "Attheraces.Com Handicap Chase",
"Distance": "5300m",
"TrackCondition": "Good",
"Weather": "Overcast",
"Abandoned": 0,
"SuspendDateTime": "2014-06-17 00:00:42.0000000",
"OutcomeDateTime": "2014-06-17 00:00:00.0000000",
"EffectiveRaceDate": "2014-06-16",
"Status": "Paying",
"Results": [
{
"event_id": 3659639,
"saddle_number": 11,
"position": 1,
"status": "Final"
},
{
"event_id": 3659639,
"saddle_number": 16,
"position": 2,
"status": "Final"
},
{
"event_id": 3659639,
"saddle_number": 17,
"position": 3,
"status": "Final"
}
],
"Dividends": {
"0": {
"event_id": 3659639,
"source": "NSW",
"pool_type": "Duet",
"outcome": "11\/16",
"pool_value": 79.5,
"interim_dividend": 11.2,
"final_dividend": 11.2
},
"36": {
"event_id": 3659639,
"source": "VIC",
"pool_type": "Trifecta",
"outcome": "11\/16\/17",
"pool_value": 1733,
"interim_dividend": 2746.2,
"final_dividend": 2746.2
},
"37": {
"event_id": 3659639,
"source": "VIC",
"pool_type": "Win",
"outcome": "11",
"pool_value": 2541.06,
"interim_dividend": 25.5,
"final_dividend": 25.5
},
"RunnerProducts": {
"11": {
"TopeTotePlace": 12,
"MidTotePlace": 7.3,
"TopeToteWin": 29.8,
"MidToteWin": 28,
"BestOrSP": 29.8
},
"16": {
"TopeTotePlace": 2.3,
"MidTotePlace": 2
},
"17": {
"TopeTotePlace": 26.4,
"MidTotePlace": 24.2
}
}
}
},
"3622800": {
"EventID": 3622800,
"RaceNum": 2,
"Meeting": "Albion Park",
"RaceType": "H",
"Description": "Seymour Rising Stars Championship C0 Heat One",
"Distance": "1660m",
"TrackCondition": "Good",
"Weather": "Fine",
"Abandoned": 0,
"SuspendDateTime": "2014-06-17 15:09:10.0000000",
"OutcomeDateTime": "2014-06-17 15:08:00.0000000",
"EffectiveRaceDate": "2014-06-17",
"Status": "Closed",
"Results": [
],
"Dividends": {
"RunnerProducts": [
]
}
},
"3679673": {
"EventID": 3679673,
"RaceNum": 6,
"Meeting": "Thirsk",
"RaceType": "T",
"Description": "Market Cross Jewellers Handicap",
"Distance": "1200m",
"TrackCondition": null,
"Weather": null,
"Abandoned": 0,
"SuspendDateTime": "2014-06-18 02:20:00.0000000",
"OutcomeDateTime": "2014-06-18 02:20:00.0000000",
"EffectiveRaceDate": "2014-06-17",
"Status": "Open",
"Results": [
],
"Dividends": {
"RunnerProducts": [
]
}
}
}
I am trying to parse this using JSON.Net and i have tried this code.
var obj = JObject.Parse(json);
var query =
from JProperty ev in obj.AsJEnumerable()
from JProperty evid in ev.Value.AsJEnumerable()
let value = (JObject)evid.Value
select new
{
Description = (string)value["Description"]
};
I am getting this error "Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'Newtonsoft.Json.Linq.JObject'."
i also want to read event_id which is inside results and dividents. Can anyone tell me what i am doing wrong here
Currently, you're getting the properties of the properties - and then trying to cast each of the values to JObject, and then taking the Description of that. That's one level too deep, as you have:
The root object
Each property of the root object, which genuinely has an object as its value
Each property of each of those values... most of which are just string properties, so the value can't be cast to JObject
It's not clear why you're using AsJEnumerable() at all, but all you need is the properties of the root object, which is easily obtained with the Properties() method. Likewise it's not clear why you're using an anonymous type, rather than just getting a sequence of strings. This works fine:
var query =
from ev in obj.Properties()
select (string) ev.Value["Description"];
Or without the query syntax:
var query = obj.Properties.Select(ev => (string) ev.Value["Description"]);
Next:
i also want to read event_id which is inside results and dividents
In the data you've given, that's always the same as the value of the EventID property in the top-level type. So you'd be better off with:
var query =
from ev in obj.Properties()
select new { Description = (string) ev.Value["Description"],
Id = (string) ev.Value["EventID"] };
If you really want to get at the values in the dividends and results, you'll need to work out how you'll handle the multiple entries in those properties.

Categories