Showing posts with label csharp. Show all posts
Showing posts with label csharp. Show all posts

Wednesday, 27 March 2013

Using C# to Get and Manipulate JSON

In my previous post I showed you how to see the JSON data that your browser was requesting from the Edgeworld server.  In this post I am going to show you how to mimic that request using C# and Visual Studio 2012.

When you look at the URL of the page request it has 2 basic parts
  • The root URL (http://sector15.c1.galactic.wonderhill.com/api/alliances/428295)
  • The URL parameters (_session_id, meltdown, reactor, user_id)
I do not know what the Edgeworld servers do with all of these parameters but I have discovered that the URL parameter of meltdown has a key value.  This value changes every time you log in to Edgeworld and it will time out once you log off.  This means that before you run a program to mimic the page request you need to log in to Edgeworld and use your developer tools to get this value and use it in your code.  The long number at the end of the string is the alliance ID.  So when you get this working for your alliance use your developer tools to find other alliance ID and track your enemies progress.

Step 1: Mimic the page request

The following code will mimic the page request.  I have created a few variables to make it easier to change out the meltdown value as mentioned above.

using System.IO;
using System.Net;

string fileContents;
string meltdown = "7463c45526b77360ffcb8d5e7f109c9d6a68048f";
string pagerequest = "http://sector15.c1.galactic.wonderhill.com/api/alliances/428295?%5Fsession%5Fid=48f319f393d1bca6ef3bed661658734a&meltdown=" + meltdown + "&reactor=4d545bca4d1d48b4d8f05685cc684a000849fb1c&user%5Fid=3608004";

WebRequest request = WebRequest.Create(@pagerequest);
WebResponse response = request.GetResponse();
Stream data = response.GetResponseStream();
string html = String.Empty;
using (StreamReader sr = new StreamReader(data))
{
    fileContents = sr.ReadToEnd();
}

For C# to use WebRequest you need to add using System.Net to the top of your program.  In the same way if you want to use Stream you need to add using System.IO.  This code will mimic the page request and save the contents of the request into a variable called fileContents.

Step 2: Parse the JSON data

Now that we have the JSON data saved into a variable it is time to parse through the data and convert it to a data structure that we can easily reference.

There are many different libraries and ways of doing this but the one I found the easiest to implement was JavaScriptSerializer.

using System.Web.Script.Serialization;

JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
PlayerData alliance = jsonSerializer.Deserialize<PlayerData>(fileContents);

To be able to use the JavaScriptSerializer you need to add a reference to your project.  To do this you need to go to Project > Add Reference. The reference that we are looking for is System.Web.Extensions and it can be found int Assemblies>Framework. Once the reference is added we need to add using System.Web.Script.Serialization to the top of our program.

The JSON data that comes from the web server is nested data that looks something like this:

{"response":
 {"timestamp":1364414863,"alliance":
  {"id":428295,"name":"ThisGameTooExpensive","description":"","members":
   [{"id":1828109,"name":"Door2Death","level":269}]
  }
 }
}

All the data is nested under response and, in this example, it has 2 variables (timestamp,alliance).  The alliance information is nested under alliance.  Then a variable under alliance is members which then nests all of the members of this particular alliance.  In order to parse through this we have to create a class to describe each nested level.  Below are four classes that parse out this data.

public class PlayerData
{
    public DataItem response { get; set; }
}
public class DataItem
{
    public int timestamp { get; set; }
    public Alliance alliance { get; set; }
    public List<Members> members { get; set; }
}
public class Alliance
{
    public int id { get; set; }
    public string name { get; set; }
}
public class Members
{
    public int id { get; set; }
    public string name { get; set; }
}

In the actual data that you will download through this method there will be more variables under each nested group.  You can simply add the variable names and the data will be added to your final data structure.

Step 3: Working with the new data structure

Now that the data is parsed into variables how do we work with it?  The advantage of Visual Studio in this case is that it will prompt you as you type out the variable structure starting with alliance once you have the above code in your program.

So if we wanted to print out the name of the alliance and then list all of the members and their respective levels to the console window we would use the code below:

Console.WriteLine(alliance.response.alliance.name);
Console.WriteLine();

for (int i = 0; i < alliance.response.members.Count;  i++)
{
    Console.WriteLine(alliance.response.members[i].id + " " + alliance.response.members[i].name);
}
Console.Read();

You can refer to a simple value like the alliance name because there is only one name or you can loop through and array of values like the list of members.  Once you understand these ideas you can then explore other things to do with the values.  Just displaying them in the console window isn't that helpful as you can see them in the alliance page.  However, if you were to save these values into an excel file and then save the values again in a week you can start tracking the progress of your alliance over time.

Thanks for reading. I have also demonstrated these ideas in the video below and the entire program is written out below the video.





using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace JSON_tutorial
{
    class Program
    {
        static void Main(string[] args)
        {
            string fileContents;
            string meltdown = "7463c45526b77360ffcb8d5e7f109c9d6a68048f";
            string pagerequest = "http://sector15.c1.galactic.wonderhill.com/api/alliances/428295?%5Fsession%5Fid=48f319f393d1bca6ef3bed661658734a&meltdown=" + meltdown + "&reactor=4d545bca4d1d48b4d8f05685cc684a000849fb1c&user%5Fid=3608004";

            WebRequest request = WebRequest.Create(@pagerequest);
            WebResponse response = request.GetResponse();
            Stream data = response.GetResponseStream();
            string html = String.Empty;
            using (StreamReader sr = new StreamReader(data))
            {
                fileContents = sr.ReadToEnd();
            }
            JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
            PlayerData alliance = jsonSerializer.Deserialize<PlayerData>(fileContents);

            Console.WriteLine(alliance.response.alliance.name);
            Console.WriteLine();
            for (int i = 0; i < alliance.response.members.Count;  i++)
            {
                Console.WriteLine(alliance.response.members[i].id + " " + alliance.response.members[i].name);
            }
            Console.Read();
        }
    }
    public class PlayerData
    {
        public DataItem response { get; set; }
    }
    public class DataItem
    {
        public int timestamp { get; set; }
        public Alliance alliance { get; set; }
        public List<Members> members { get; set; }
    }
    public class Alliance
    {
        public int id { get; set; }
        public string name { get; set; }
    }
    public class Members
    {
        public int id { get; set; }
        public string name { get; set; }
    }
}