0

I attempting to write out a list of strings to the console but get this output: System.Collections.Generic.List`1[System.String]

I think i might be formating the code wrong or i need to convert it somehow.

This is what my list looks like (Rows is a property in GaData class and a list of strings):

List<string> ListDates = new List<string>(new string[] { d.Rows.ToString()});

Console.WriteLine(ListDates);
Console.ReadLine();

And this is the property of GaData class:

public virtual IList<IList<string>> Rows { get; set; }

I'm working on retrieving some data i collect from Google Analytics API. Im trying to use the property "Rows" from google GaData class wich is a list of strings. Rows also contains more vaules like StartDate, EndDate, Visitors, NewVisits, Pageviews, PercentNewVisits, all of these parameeters are value of a keyValuePair. For example:

KeyValuePair Visitors: key = "ga:visitors" value =3000 (The actual number of visitors).

Hers the data i get when debugging:

enter image description here

Hers the GaData class from google:

enter image description here

Here's the class with KeyValuePairs from Google. It uses metrics, demensions and sort to filter data from google api. For example: metrics="visitors", Demensions="ga:date", sort="ga:visits". enter image description here

Don't know if it's nessessary but here is the code:

My Google API client:

public static void Main(string[] args)
            {
                var serviceAccountEmail = "User@developer.gserviceaccount.com";

                var certificate = new X509Certificate2(@"C:\Users\User\Desktop\key.p12", "notasecret", X509KeyStorageFlags.Exportable);




                var credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(serviceAccountEmail)
                {
                    Scopes = new[] { AnalyticsService.Scope.Analytics }
                }.FromCertificate(certificate));

                // Create the service.
                //Twistandtango
                var gas = new AnalyticsService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "TestGoogleAnalytics",
                });

                var r = gas.Data.Ga.Get("ProfileID", "2014-01-24", "2014-02-28", "ga:pageviews,ga:newVisits,ga:visitors,ga:percentNewVisits");


                r.Dimensions = "ga:date";
                r.Sort = "-ga:date";
                r.MaxResults = 10000;



                //Execute and fetch the results of our query
                Google.Apis.Analytics.v3.Data.GaData d = r.Execute();



                //output Rows with all visitor data for each date between StartDate and EndDate
                List<string> ListDates = new List<string>(new string[] { d.Rows.ToString()});

                Console.WriteLine(ListDates);
                Console.ReadLine();





                //Output actuall values - visitors, newVisits, pageviews and percentNewVisits
                Console.WriteLine("Besöksstatistik" + "  " + 
                    d.Query.StartDate + " " + "-" + " " + d.Query.EndDate + "\r\n" +
                    "------------------------------------------" + "\r\n" +
                 "Antal besökare:" + " " + d.TotalsForAllResults["ga:visitors"] + "\r\n" +
                 "Antal nya besökare:" + " " + d.TotalsForAllResults["ga:newVisits"] + "\r\n" +
                 "Sidvisningar:" + " " + d.TotalsForAllResults["ga:pageviews"] + "\r\n" +
                 "Procent nya besökare:" + " " + d.TotalsForAllResults["ga:percentNewVisits"] +"%");


                Console.ReadLine();

GaData class (Google):

    public class GaData : IDirectResponseSchema
    {
        public GaData();

        // Summary:
        //     Column headers that list dimension names followed by the metric names. The
        //     order of dimensions and metrics is same as specified in the request.
        [JsonProperty("columnHeaders")]
        public virtual IList<GaData.ColumnHeadersData> ColumnHeaders { get; set; }
        //
        // Summary:
        //     Determines if Analytics data contains samples.
        [JsonProperty("containsSampledData")]
        public virtual bool? ContainsSampledData { get; set; }
        [JsonProperty("dataTable")]
        public virtual GaData.DataTableData DataTable { get; set; }
        //
        // Summary:
        //     The ETag of the item.
        public virtual string ETag { get; set; }
        //
        // Summary:
        //     Unique ID for this data response.
        [JsonProperty("id")]
        public virtual string Id { get; set; }
        //
        // Summary:
        //     The maximum number of rows the response can contain, regardless of the actual
        //     number of rows returned. Its value ranges from 1 to 10,000 with a value of
        //     1000 by default, or otherwise specified by the max-results query parameter.
        [JsonProperty("itemsPerPage")]
        public virtual int? ItemsPerPage { get; set; }
        //
        // Summary:
        //     Resource type.
        [JsonProperty("kind")]
        public virtual string Kind { get; set; }
        //
        // Summary:
        //     Link to next page for this Analytics data query.
        [JsonProperty("nextLink")]
        public virtual string NextLink { get; set; }
        //
        // Summary:
        //     Link to previous page for this Analytics data query.
        [JsonProperty("previousLink")]
        public virtual string PreviousLink { get; set; }
        //
        // Summary:
        //     Information for the view (profile), for which the Analytics data was requested.
        [JsonProperty("profileInfo")]
        public virtual GaData.ProfileInfoData ProfileInfo { get; set; }
        //
        // Summary:
        //     Analytics data request query parameters.
        [JsonProperty("query")]
        public virtual GaData.QueryData Query { get; set; }
        //
        // Summary:
        //     Analytics data rows, where each row contains a list of dimension values followed
        //     by the metric values. The order of dimensions and metrics is same as specified
        //     in the request.
        [JsonProperty("rows")]
        public virtual IList<IList<string>> Rows { get; set; }
        //
        // Summary:
        //     The number of samples used to calculate the result.
        [JsonProperty("sampleSize")]
        public virtual long? SampleSize { get; set; }
        //
        // Summary:
        //     Total size of the sample space from which the samples were selected.
        [JsonProperty("sampleSpace")]
        public virtual long? SampleSpace { get; set; }
        //
        // Summary:
        //     Link to this page.
        [JsonProperty("selfLink")]
        public virtual string SelfLink { get; set; }
        //
        // Summary:
        //     The total number of rows for the query, regardless of the number of rows
        //     in the response.
        [JsonProperty("totalResults")]
        public virtual int? TotalResults { get; set; }
        //
        // Summary:
        //     Total values for the requested metrics over all the results, not just the
        //     results returned in this response. The order of the metric totals is same
        //     as the metric order specified in the request.
        [JsonProperty("totalsForAllResults")]
        public virtual IDictionary<string, string> TotalsForAllResults { get; set; }

Here is the Google class with parameeters to filter data from the API:

 // Summary:
            //     Returns Analytics data for a view (profile).
            public class GetRequest : AnalyticsBaseServiceRequest<Google.Apis.Analytics.v3.Data.GaData>
            {
                // Summary:
                //     Constructs a new Get request.
                public GetRequest(IClientService service, string ids, string startDate, string endDate, string metrics);

                // Summary:
                //     A comma-separated list of Analytics dimensions. E.g., 'ga:browser,ga:city'.
                [RequestParameter("dimensions", RequestParameterType.Query)]
                public virtual string Dimensions { get; set; }
                //
                // Summary:
                //     End date for fetching Analytics data. Request can should specify an end date
                //     formatted as YYYY-MM-DD, or as a relative date (e.g., today, yesterday, or
                //     7daysAgo). The default value is yesterday.
                [RequestParameter("end-date", RequestParameterType.Query)]
                public virtual string EndDate { get; }
                //
                // Summary:
                //     A comma-separated list of dimension or metric filters to be applied to Analytics
                //     data.
                [RequestParameter("filters", RequestParameterType.Query)]
                public virtual string Filters { get; set; }
                //
                // Summary:
                //     Gets the HTTP method.
                public override string HttpMethod { get; }
                //
                // Summary:
                //     Unique table ID for retrieving Analytics data. Table ID is of the form ga:XXXX,
                //     where XXXX is the Analytics view (profile) ID.
                [RequestParameter("ids", RequestParameterType.Query)]
                public virtual string Ids { get; }
                //
                // Summary:
                //     The maximum number of entries to include in this feed.
                [RequestParameter("max-results", RequestParameterType.Query)]
                public virtual int? MaxResults { get; set; }
                //
                // Summary:
                //     Gets the method name.
                public override string MethodName { get; }
                //
                // Summary:
                //     A comma-separated list of Analytics metrics. E.g., 'ga:visits,ga:pageviews'.
                //     At least one metric must be specified.
                [RequestParameter("metrics", RequestParameterType.Query)]
                public virtual string Metrics { get; }
                //
                // Summary:
                //     The selected format for the response. Default format is JSON.
                [RequestParameter("output", RequestParameterType.Query)]
                public virtual DataResource.GaResource.GetRequest.OutputEnum? Output { get; set; }
                //
                // Summary:
                //     Gets the REST path.
                public override string RestPath { get; }
                //
                // Summary:
                //     The desired sampling level.
                [RequestParameter("samplingLevel", RequestParameterType.Query)]
                public virtual DataResource.GaResource.GetRequest.SamplingLevelEnum? SamplingLevel { get; set; }
                //
                // Summary:
                //     An Analytics advanced segment to be applied to data.
                [RequestParameter("segment", RequestParameterType.Query)]
                public virtual string Segment { get; set; }
                //
                // Summary:
                //     A comma-separated list of dimensions or metrics that determine the sort order
                //     for Analytics data.
                [RequestParameter("sort", RequestParameterType.Query)]
                public virtual string Sort { get; set; }
                //
                // Summary:
                //     Start date for fetching Analytics data. Requests can specify a start date
                //     formatted as YYYY-MM-DD, or as a relative date (e.g., today, yesterday, or
                //     7daysAgo). The default value is 7daysAgo.
                [RequestParameter("start-date", RequestParameterType.Query)]
                public virtual string StartDate { get; }
                //
                // Summary:
                //     An index of the first entity to retrieve. Use this parameter as a pagination
                //     mechanism along with the max-results parameter.
                [RequestParameter("start-index", RequestParameterType.Query)]
                public virtual int? StartIndex { get; set; }

                // Summary:
                //     Initializes Get parameter list.
                protected override void InitParameters();

                // Summary:
                //     The selected format for the response. Default format is JSON.
                public enum OutputEnum
                {
                    // Summary:
                    //     Returns the response in Google Charts Data Table format. This is useful in
                    //     creating visualization using Google Charts.
                    [StringValue("dataTable")]
                    DataTable = 0,
                    //
                    // Summary:
                    //     Returns the response in standard JSON format.
                    [StringValue("json")]
                    Json = 1,
                }

                // Summary:
                //     The desired sampling level.
                public enum SamplingLevelEnum
                {
                    // Summary:
                    //     Returns response with a sample size that balances speed and accuracy.
                    [StringValue("DEFAULT")]
                    DEFAULT = 0,
                    //
                    // Summary:
                    //     Returns a fast response with a smaller sample size.
                    [StringValue("FASTER")]
                    FASTER = 1,
                    //
                    // Summary:
                    //     Returns a more accurate response using a large sample size, but this may
                    //     result in the response being slower.
                    [StringValue("HIGHER_PRECISION")]
                    HIGHERPRECISION = 2,
                }
            }
        }

What i wan't to archive is this:

enter image description here

Again my actuall question is how i can display the data from "Rows" property in GaData class. Allthough you might make more sence of this than i and a better solution to get the data to display in the console.

I would be very greatful for anny help!!

Thank you

//Chriss

WhoAmI
  • 1,188
  • 6
  • 17
  • 47

4 Answers4

1

Try something like this:

For example for the Visitors in each row. As you said, each row has properties right? like Visitors for example, and each Visitor has key/value pair.

foreach (var row in d.Rows)
{
    Console.WriteLine(string.Format("Visitors: {0}, Visits: {1}", row.Visitors.Key, row.Visitors.Value));
}
Oscar Bralo
  • 1,912
  • 13
  • 12
  • Yes something like this migth be the solution! However "Rows" is a property -public virtual IList> Rows { get; set; } that contains dictionaries. For exempel the dictionary for "visitors" has key="ga:visitors" and value="1000" (nr of visitors. – WhoAmI Mar 08 '14 at 10:04
  • Yes, each row is a dictionary, and thats why with this foreach loop, row will be a KeyValuePair, which contains key and value, row.Visitors.Key will be ga:visitors and row.Visitors.Value will be 1000 ;) – Oscar Bralo Mar 08 '14 at 11:33
  • Righ, i get what you mean. I'll play around this concept and see what happens. Thanks! =) – WhoAmI Mar 08 '14 at 18:50
  • I hope this helps Kristoffer! ;) – Oscar Bralo Mar 08 '14 at 18:59
1

You can get the information about how the result of a query looks like under: https://developers.google.com/apis-explorer/#search/analytics/analytics/v3/analytics.data.ga.get

d.Rows[0][0] shows you the first result of the query and I would output it like this:

Console.WriteLine("{0}: {1}", d.ColumnHeaders[0].Name, d.Rows[0][0]);
francis
  • 9,525
  • 2
  • 25
  • 41
Waterpolo
  • 11
  • 1
0

You need just one more loop for the inner list:

List<string> ListDates = new List<string>(new string[] { d.Rows.ToString()});

foreach(var str in list){
    Console.WriteLine(str);
}

Console.ReadLine();

Also check out String.Format static method so you can format your strings nicely(it may be used instead of d.Rows.ToString when fulfilling the list)

Blablablaster
  • 3,238
  • 3
  • 31
  • 33
  • I see, thx. I do get a list now but the output is still System.Collection.Generic.List`1[System.String] but vertically. Here's an image https://imageshack.com/i/e9tabpp – WhoAmI Mar 08 '14 at 09:59
0

A foreach is certainly the most clear and obvious when you come back to the code, but if you really want it all on one line you could use some LINQ magic ... this is two ways of of achieving the same thing.

        var values = new List<string> { "a", "b", "c" };

        foreach (var v in values)
            Console.WriteLine(v);

        Console.WriteLine(values.Aggregate("", (current, next) => current + Environment.NewLine + next));

Just remember to include System.Linq for Aggregate.

In either case you'll need to dig into the Rows property since it is a nested IList. So you'll need to double up on the foreach or Aggregate, e.g.

        var values = new List<List<string>> { new List<string>{"a", "b"}, new List<string>{"c"} };

        foreach (var v in values)
        foreach (var innerValue in v)
        Console.WriteLine(innerValue);

        Console.WriteLine(values.Aggregate("", (current, next) => current + Environment.NewLine + next.Aggregate("", (c, n) => c + Environment.NewLine + n).Trim(new []{'\r', '\n'})));
Kyle
  • 1
  • 1
  • This is a very interesting input. Thanks for explaining, i will dig deeper in to this subject and see what i can come up with. Thank you!One thing that is wierd though is that Rows contains all the data i'm querying to Google- StartDate, EndDate, Visitors, Date etc However i can't seem to reach to access them separately. For ex if i write d.TotalsForAllResults["ga:visitors"] i will get the out put "ga:visitors 3500" where ga:visitors is the Key and the 3500 is the Value, eg a dictionary. I can't get this output with d.Rows however – WhoAmI Mar 08 '14 at 10:31