user1769025
user1769025

Reputation: 21

Consuming JSON in C# from mailchimp campaignEmailStatsAIMAll

I am trying to program .net c# code to read the results from a call to campaignEmailStatsAIMAll().

Here is a sample of the JSON results I get:

{
   "total":3,
   "data":{
      "[email protected]":[
         {
            "action":"click",
            "timestamp":"2012-10-18 20:55:52",
            "url":"http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)",
            "ip":"66.66.666.666"
         },
         {
            "action":"open",
            "timestamp":"2012-10-18 20:55:52",
            "url":null,
            "ip":"66.66.666.666"
         }
      ],
      "[email protected]":[
         {
            "action":"open",
            "timestamp":"2012-10-18 20:18:05",
            "url":null,
            "ip":"22.222.222.222"
         },
         {
            "action":"open",
            "timestamp":"2012-10-18 20:18:18",
            "url":null,
            "ip":"22.222.222.222"
         },
         {
            "action":"click",
            "timestamp":"2012-10-18 20:18:18",
            "url":"http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)",
            "ip":"22.222.222.222"
         },
         {
            "action":"click",
            "timestamp":"2012-10-18 20:21:57",
            "url":"http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)",
            "ip":"22.222.222.222"
         }
      ],
      "[email protected]":[

      ]
   }
}

The problem I am having is how to define the C# object to accept this JSON string. The email addresses are being treated as the name part of a JSON name/value pair. I know there are 3rd party wrappers for .NET but I only want to call this API (maybe a couple of others down the line) and would prefer to code it myself. I want to be able to iterate through the object to extract the email address then action/timestamp/url for each one.

When I drop this JSON into the object creator at json2sharp.com, I get this:

public class SomebodyCompanyCom {     
   public string action { get; set; }     
   public string timestamp { get; set; }     
   public string url { get; set; }     
   public string ip { get; set; } 
}

public class AnotherpersonCorporationCom {     
   public string action { get; set; }      
   public string timestamp { get; set; }     
   public string url { get; set; }     
   public string ip { get; set; } 
}

public class Data {     
   public List<SomebodyCompanyCom> [email protected] { get; set; }     
   public List<AnotherpersonCorporationCom> [email protected] { get; set; }     
   public List<object> [email protected] { get; set; } 
}

public class RootObject {     
   public int total { get; set; }     
   public Data data { get; set; } 
}

Upvotes: 2

Views: 541

Answers (1)

Drew Shafer
Drew Shafer

Reputation: 4802

A generator like that can only ever make best-guesses. Since JSON is generally schema-less, you need to analyze the data and figure out the best way to model it.

In your case, you have two basic types:

  1. the individual entries consisting of action, timestamp, url, and ip
  2. the overall container with total and data

A reasonable model might look like this:

public class ItemInfo {     
   public string action { get; set; }     
   public string timestamp { get; set; }     
   public string url { get; set; }     
   public string ip { get; set; } 
}

public class ContainerType {
    public int total;
    public Dictionary<string, ItemInfo[]> data;
}

If you use a decent JSON library like JSON.Net, you could deserialize the JSON string into an ContatinerType structure like so:

string rawJsonString = MagicallyGetTheJsonFromAWebservice();
ContainerType container = JsonConvert.DeserializeObject<ContainerType>(rawJsonString);

It might need a bit of tweaking to get the type deserialization to work exactly, but that's the basic idea.

Edit: sample console program to do the deserialization:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

namespace ConsoleApplication1
{
    class Program
    {
        static string testData = @"{
   'total':3,
   'data':{
      '[email protected]':[
         {
            'action':'click',
            'timestamp':'2012-10-18 20:55:52',
            'url':'http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)',
            'ip':'66.66.666.666'
         },
         {
            'action':'open',
            'timestamp':'2012-10-18 20:55:52',
            'url':null,
            'ip':'66.66.666.666'
         }
      ],
      '[email protected]':[
         {
            'action':'open',
            'timestamp':'2012-10-18 20:18:05',
            'url':null,
            'ip':'22.222.222.222'
         },
         {
            'action':'open',
            'timestamp':'2012-10-18 20:18:18',
            'url':null,
            'ip':'22.222.222.222'
         },
         {
            'action':'click',
            'timestamp':'2012-10-18 20:18:18',
            'url':'http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)',
            'ip':'22.222.222.222'
         },
         {
            'action':'click',
            'timestamp':'2012-10-18 20:21:57',
            'url':'http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)',
            'ip':'22.222.222.222'
         }
      ],
      '[email protected]':[

      ]
   }
}";

        public class ItemInfo {     
           public string action { get; set; }     
           public string timestamp { get; set; }     
           public string url { get; set; }     
           public string ip { get; set; } 
        }

        public class ContainerType {
            public int total;
            public Dictionary<string, ItemInfo[]> data;
        }
        static void Main(string[] args)
        {
            ContainerType container = JsonConvert.DeserializeObject<ContainerType>(testData);
            if((container.total != 3)
                || (container.data.Count != 3)
                || (container.data["[email protected]"][1].action != "open")
                || (container.data["[email protected]"][2].url != "http://www.someurl.com?ct=t(First_Chimp_Test10_18_2012)"))
            {
                Console.WriteLine("Failed to deserialize");
            }
            else
            {
                Console.WriteLine("Successfully deserialized");
            }

            foreach (string email in container.data.Keys)
            {
                Console.WriteLine(email);
                for (int x = 0; x < container.data[email].Count(); x++)
                {
                    Console.WriteLine("\t" + x.ToString() + ":");
                    Console.WriteLine("\t\taction   : " + container.data[email][x].action);
                    Console.WriteLine("\t\ttimestamp: " + container.data[email][x].timestamp);
                    Console.WriteLine("\t\turl      : " + container.data[email][x].url);
                    Console.WriteLine("\t\tip       : " + container.data[email][x].ip);
                }
            }
        }
    }
}

Upvotes: 1

Related Questions