1

My JSON looks like this:

 {"2013" : [
 { "date":"2013-01-09 12:00:00","height":0 },
 { "date":"2013-01-19 12:00:00","height":3 },
 { "date":"2013-01-29 12:00:00","height":2 }],
 "2012" : [
 { "date":"2012-02-09 12:00:00","height":0 },
 { "date":"2012-02-19 12:00:00","height":4 },
 { "date":"2012-02-29 12:00:00","height":2 }],
 "2011" : [
 { "date":"2011-03-09 12:00:00","height":3 },
 { "date":"2011-03-19 12:00:00","height":8 },
 { "date":"2011-03-29 12:00:00","height":2 }]
 }

What I am trying to do is get all of the dates and height, but I am only able to do it per year using this code:

 public class Report
 {
 public DateTime Date { get; set; }
 public int Height { get; set; }
 }
 JObject data = JObject.Parse(sr);
 var postTitles = from p in data["2013"]
 select new Report
 {
 Date = DateTime.Parse((string)p["date"]),
 Height = (int)p["height"]
 };

I was thinking of using a for loop but trying a variable inside data[" "] won't work. I was also thinking of doing var postTitles += statement but it is not allowed as well. Any ideas on how I should go about this? I am using JSON.NET and it is suggested that I do a class per year (i.e. 2013, 2012, 2011) but I want them under one class to make it easier to manipulate data.

asked Jul 11, 2013 at 7:21

2 Answers 2

1

I am not that great with the LINQ syntax you are using but what you want to do is create a list from many lists. So you want to use the SelectMany mapping operation from LINQ.

var postTitles = data.Children()
 .SelectMany(subitems => subitems.First)
 .Select(dataOfYear =>
 new Report
 {
 Date = DateTime.Parse((string)dataOfYear ["date"]),
 Height = (int)dataOfYear ["height"]
 }
 );

If you want only the first 100 reports of every year you could do it like this:

var postTitles = data.Children()
 .SelectMany(subitems => subitems.First)
 .Take(100)
 .Select(dataOfYear =>
 new Report
 {
 Date = DateTime.Parse((string)dataOfYear ["date"]),
 Height = (int)dataOfYear ["height"]
 }
 );

Or if you just want to free up the UI thread you could run this in a background thread:

var postTitles = await Task.Run(() => data.Children()
 .SelectMany(subitems => subitems.First)
 .Select(dataOfYear =>
 new Report
 {
 Date = DateTime.Parse((string)dataOfYear ["date"]),
 Height = (int)dataOfYear ["height"]
 }
 ));
answered Jul 11, 2013 at 7:36
Sign up to request clarification or add additional context in comments.

2 Comments

Is there something missing after the "dataOfYear =>" statement?
@CCCC sorry I used another dummy structure for testing, after loading the json data with JSON.Net I came to the same conclusion as PatrikW
0

I turned and twisted Mark's anwer somewhat and came up with this:

var postTitles = data.Children() // Select array container properties, like "2013"
 .SelectMany(x => x.First) // Select each subitem from every array
 .Select(r => // Create a report for each item
 new Report
 {
 Date = DateTime.Parse((string)r["date"]),
 Height = (int)r["height"]
 }
 );

Hopefully the inline comments will explain the logic sufficiently.

answered Jul 11, 2013 at 9:31

2 Comments

It did work. Thank you! Building on your question. The data is actually too large so my app suddenly lags. Say, If I am going to to choose the first 100 "Reports", will a for loop work? Because right now, I am using a a foreach (var s in postTitles) loop, using s.Date and s.Height to reference each. How would I go about it if I change it to for loop?
@CCCC See Mark's updated answer for solutions to that problem.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.