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)
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; } } }
Nice post. I have thought about building a better interface for the engineering lab. The API seems straight forward with a call using the part ID, but for the life of me I can't seem to find a good way to get a list of all the parts I have. When that window is created, it is all done with javascript... any idea on how to tease that info out?
ReplyDeleteI haven't looked into the Eng Lab yet. I will look into that tonight and see if I can figure anything out there.
DeleteIf you already understand the stuff in my previous posts please try to use this:
Deleteapi/player/equipment?meltdown=blah&_session_id=null&reactor=blah&user_id=blah
Cheers
Very nice!
ReplyDeletepublic class Equipment
{
public int id { get; set; }
public string type { get; set; }
public int level { get; set; }
public int durability { get; set; }
public bool equipped { get; set; }
public int? base_id { get; set; }
public string building_type { get; set; }
}
public class Response
{
public int timestamp { get; set; }
public List equipment { get; set; }
public bool success { get; set; }
}
public class RootObject
{
public Response response { get; set; }
public string x { get; set; }
public string y { get; set; }
}
Well you definitely understood the previous post :). Nice work. I will have to find a use for that now.
DeleteI am now working on a map monitoring tool that can help keep track of base counts so I know when we are attacked. I added a new tab to this page to list out the known APIs. Thanks for your help.
thanks, how can i handle the case that i don't have the namse of the propoties in the json file ?
ReplyDelete