I've been trying to use the steam storefront api http://store.steampowered.com/api/ .
The problem is that when I feed the result of the api to RestSharp, the data is always null.
So my question is how do I get the Rest call deserialized?
First, this is what you would be expecting when calling appdetails?appids=[appid]
{
"3400": {
"success": true,
"data": {
"type": "game",
"name": "Hammer Heads Deluxe",
"steam_appid": 3400,
"required_age": 0,
"is_free": false,
"detailed_description": "",
"about_the_game": "",
"short_description": "",
"supported_languages": "English",
"header_image": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/header.jpg?t=1447350883",
"website": null,
"pc_requirements": {
"minimum": "<p><strong>Minimum Requirements:<\/strong> Windows 98\/ME\/2000\/XP, 128 MB RAM, 500MHz or faster, DirectX: 7.0<\/p>"
},
"mac_requirements": [
],
"linux_requirements": [
],
"developers": [
"PopCap Games, Inc."
],
"publishers": [
"PopCap Games, Inc."
],
"demos": [
{
"appid": 3402,
"description": ""
}
],
"price_overview": {
"currency": "USD",
"initial": 499,
"final": 499,
"discount_percent": 0
},
"packages": [
135
],
"package_groups": [
{
"name": "default",
"title": "Buy Hammer Heads Deluxe",
"description": "",
"selection_text": "Select a purchase option",
"save_text": "",
"display_type": 0,
"is_recurring_subscription": "false",
"subs": [
{
"packageid": 135,
"percent_savings_text": "",
"percent_savings": 0,
"option_text": "Hammer Heads Deluxe - $4.99",
"option_description": "",
"can_get_free_license": "0",
"is_free_license": false,
"price_in_cents_with_discount": 499
}
]
}
],
"platforms": {
"windows": true,
"mac": false,
"linux": false
},
"categories": [
{
"id": 2,
"description": "Single-player"
}
],
"genres": [
{
"id": "4",
"description": "Casual"
}
],
"screenshots": [
{
"id": 0,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000564.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000564.1920x1080.jpg?t=1447350883"
},
{
"id": 1,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000565.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000565.1920x1080.jpg?t=1447350883"
},
{
"id": 2,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000566.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000566.1920x1080.jpg?t=1447350883"
},
{
"id": 3,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000567.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000567.1920x1080.jpg?t=1447350883"
},
{
"id": 4,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000568.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000568.1920x1080.jpg?t=1447350883"
}
],
"release_date": {
"coming_soon": false,
"date": "Aug 30, 2006"
},
"support_info": {
"url": "",
"email": ""
},
"background": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/page_bg_generated_v6b.jpg?t=1447350883"
}
}
}
That is the json block returned for accessing appid 3400. Note how it's appid is located inside of file itself.
In order to generate classes for this, I made a formatted version of that based off the unofficial storefront api documentation . Then I used that to generate the container classes shown below.
public class Appid
{
public bool success { get; set; }
public Data data { get; set; }
}
public class Data
{
public string type { get; set; }
public string name { get; set; }
public int steam_appid { get; set; }
public int required_age { get; set; }
public int[] dlc { get; set; }
public string detailed_description { get; set; }
public string about_the_game { get; set; }
public Fullgame fullgame { get; set; }
public string supported_languages { get; set; }
public string header_image { get; set; }
public string website { get; set; }
public Pc_Requirements pc_requirements { get; set; }
public Mac_Requirements mac_requirements { get; set; }
public Linux_Requirements linux_requirements { get; set; }
public string[] developers { get; set; }
public Demos demos { get; set; }
public Price_Overview price_overview { get; set; }
public int[] packages { get; set; }
public Package_Groups[] package_groups { get; set; }
public Platforms platforms { get; set; }
public Metacritic metacritic { get; set; }
public Category[] categories { get; set; }
public Screenshot[] screenshots { get; set; }
public Movie[] movies { get; set; }
public Recommendations recommendations { get; set; }
public Achievements achievements { get; set; }
public Release_Date release_date { get; set; }
}
public class Fullgame
{
public int appid { get; set; }
public string name { get; set; }
}
public class Pc_Requirements
{
public string minimum { get; set; }
public string recommended { get; set; }
}
public class Mac_Requirements
{
public string minimum { get; set; }
public string recommended { get; set; }
}
public class Linux_Requirements
{
public string minimum { get; set; }
public string recommended { get; set; }
}
public class Demos
{
public int appid { get; set; }
public string description { get; set; }
}
public class Price_Overview
{
public string currency { get; set; }
public int initial { get; set; }
public int final { get; set; }
public int discount_precent { get; set; }
}
public class Platforms
{
public bool windows { get; set; }
public bool mac { get; set; }
public bool linux { get; set; }
}
public class Metacritic
{
public int score { get; set; }
public string url { get; set; }
}
public class Recommendations
{
public int total { get; set; }
}
public class Achievements
{
public int total { get; set; }
public Highlighted[] highlighted { get; set; }
}
public class Highlighted
{
public string name { get; set; }
public string path { get; set; }
}
public class Release_Date
{
public bool coming_soon { get; set; }
public string date { get; set; }
}
public class Package_Groups
{
public string name { get; set; }
public string title { get; set; }
public string description { get; set; }
public string selection_text { get; set; }
public string save_text { get; set; }
public int display_type { get; set; }
public string is_recurring_subscription { get; set; }
public Sub[] subs { get; set; }
}
public class Sub
{
public int packageid { get; set; }
public string percent_savings_text { get; set; }
public int percent_savings { get; set; }
public string option_text { get; set; }
public string option_description { get; set; }
}
public class Category
{
public int id { get; set; }
public string description { get; set; }
}
public class Screenshot
{
public int id { get; set; }
public string path_thumbnail { get; set; }
public string path_full { get; set; }
}
public class Movie
{
public int id { get; set; }
public string name { get; set; }
public string thumbnail { get; set; }
public Webm webm { get; set; }
}
public class Webm
{
public string _480 { get; set; }
public string max { get; set; }
}
Now onto the code, the function takes in a long and should return a Data object. However, instead of deserializing, it returns a null. I have checked to make sure the json is actually getting to the code. It is coming in fine.
//Steam rest stuff always returns with one object.
//This it to keep me writing 10 classes that do essentially the same thing
//And before you ask, yes, I have tried doing this without this class.
//Still didn't work.
public class RootObject<T>
{
public T response { get; set; }
}
public static Data GetGameData(long appid)
{
//Only thing different about this function except for the fact that it's also static
RestClient storeClient = new RestClient("http://store.steampowered.com/api/");
RestRequest restReq = new RestRequest("appdetails/", Method.GET);
restReq.AddParameter("appids", appid);
restReq.RequestFormat = DataFormat.Json;
restReq.OnBeforeDeserialization = resp =>
{
//This was done as an attempt to fix it.
//It makes the appid's in the content into {"appId":{
//EX: {"400":{ -> {"appId":{
resp.Content = Regex.Replace(resp.Content, "{\"\\d+\":{", "{\"appId\":{");
};
IRestResponse<RootObject<Appid>> response = storeClient.Execute<RootObject<Appid>>(restReq);
Appid trueRes = response.Data.response;
return trueRes.data;
}
Quick note, the function was altered but only to work in a static context. The edit was noted in code.
Things I've tried
Dictionary<string, Appid>
instead of RootObject<Appid>
Edit: For some extra information I did some testing on the methods. I remade the object carrying classes using appid 4000 and put that into json to sharp converter. Then I wrote a small bit of code that tested if the data was null.
static void TestIfFetched(long appid)
{
Console.Write($"{appid}\t:");
Data data = GetGameData(appid);
if (data == null)
{
Console.WriteLine("Failed to get data.");
}
else
{
Console.WriteLine("Data fetched successfully.");
}
}
The result was this when testing 4000 and 400.
4000 :Failed to get data.
400 :Failed to get data.
So it seems even using data specifically designed for that game, it still fails to parse.
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
RestClient storeClient = new RestClient("https://store.steampowered.com/api/");
RestRequest restReq = new RestRequest("appdetails/", Method.GET);
restReq.AddParameter("appids", appid);
restReq.RequestFormat = DataFormat.Json;
var response = storeClient.Execute<dynamic>(restReq);
JObject jObject = JObject.Parse(response.Content);
var details = jObject[appid].Value<JObject>().ToObject<Appid>();
The above worked for me. The JObject allows you to pass the appid as a parameter and then parse your object from there.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.