我试图从一个名为backpack.tf.的站点创建一个使用API的应用程序
我面临一个问题,我有一个存储数据的文件:
class currencyData
{
public CurrencyResponse currencyResponse { get; set; }
}
public class CurrencyResponse
{
public int success { get; set; }
public int current_time { get; set; }
public int raw_usd_value { get; set; }
public int usd_currency { get; set; }
public int usd_currency_index { get; set; }
public Dictionary<string, CurrencyPrices> items { get; set; }
}
public class CurrencyPrices
{
public int currency { get; set; }
public int value { get; set; }
public int value_high { get; set; }
public int value_raw { get; set; }
public int value_high_raw { get; set; }
public int last_update { get; set; }
public int difference { get; set; }
}
基本上,我尝试存储JSON数据的代码是:
//make call to the API and retrieve JSON data
char[] array1 = { };
char[] array2 = { };
System.Net.WebClient client = new System.Net.WebClient();
System.Net.WebClient client2 = new System.Net.WebClient();
client.Headers.Add("key-price", "application/json");
client2.Headers.Add("item-data", "application/json");
//get the JSON data.
string test = Encoding.ASCII.GetString(client.UploadData("http://backpack.tf/api/IGetCurrencies/v1/?key=54972a10b88d885f748b4956&appid=440&compress=1", "POST", Encoding.Default.GetBytes(array1)));
string currencyJSON = Encoding.ASCII.GetString(client2.UploadData("http://backpack.tf/api/IGetPrices/v4/?key=54972a10b88d885f748b4956&appid=440&compress=1", "POST", Encoding.Default.GetBytes(array2)));
//deserialize json data and store it in rootObject.cs
rootObject obj = JsonConvert.DeserializeObject<rootObject>(test);
//same as above but store itt in currencyData.cs
currencyData currencyData = JsonConvert.DeserializeObject<currencyData>(currencyJSON);
Response response = obj.response;
CurrencyResponse currencyResponse = currencyData.currencyResponse;
//check if the API responds, If not we can display an error message
if (response.success == 1 ) {
foreach (KeyValuePair<string, Currency> kvp in response.currencies)
{
string currencyName = kvp.Key;
Currency currency = kvp.Value;
}
foreach (KeyValuePair<string, CurrencyPrices> currencyDataDict in currencyResponse.items)
{
string itemName = currencyDataDict.Key;
CurrencyPrices currencyPrices = currencyDataDict.Value;
}
Currency kek = new Currency();
outputBox.Text = test;
}
rootObject:
class rootObject
{
public Response response { get; set; }
}
public class Response
{
public int success { get; set; }
public int current_time { get; set; }
public Dictionary<string, Currency> currencies { get; set; }
public string name { get; set; }
public string url { get; set; }
}
public class Currency
{
public int quality { get; set; }
public int priceindex { get; set; }
public string single { get; set; }
public string plural { get; set; }
public int round { get; set; }
public string craftable { get; set; }
public string tradable { get; set; }
public int active { get; set; }
public int defindex { get; set; }
}
现在我的问题是数据没有在第二个API调用中检索,如果我删除第二个foreach循环,它将输出包含JSON数据的变量Test。但是,如果我保留第二个foreach循环,则它将不打印任何内容。。
提前表示感谢,并对措辞不当等表示歉意。背包.tf API文档
currencyData
:有很多问题
-
返回的JSON实际上与文档不匹配(Backpack.tf):
1.1.名为
"Untradable"
的字段实际返回为"Non-Tradable"
1.2.名为
"Uncraftable"
的字段实际返回为"Non-Craftable"
。1.3.
"Craftable"
对象应该在数量到价格数据的字典中返回。事实上,它们是,有时作为数组返回:"Craftable": [ { "currency": "metal", "value": 1.33, "last_update": 1417451879, "difference": -0.11 } ] But they are *sometimes* returned as a dictionary! "Craftable": { "10": { "currency": "usd", "value": 101.49, "value_high": 124.04, "last_update": 1362682641, "difference": 34.719 }, "11": { "currency": "earbuds", "value": 1.4, "last_update": 1406474947, "difference": 31.236, "value_high": 1.8 },
-
您有几个声明为
int
的字段,这些字段可以包含小数数据。它们需要更改为其他内容,例如decimal
。 -
您的数据模型与文档模型不匹配,文档模型比您的模型更深几个层次。
currencyData
的以下代码和对象读取文档中显示的JSON和调用实际返回的JSON,因为我认为两者都必须处理。还应注意文件中的以下资格:
每个API密钥每分钟只能向此API发出一个请求。此外,响应会被缓存并每10分钟更新一次。
所以,请确保你不会经常收到价格。
[DataContract]
public class currencyData
{
[DataMember(Name="response")]
public CurrencyResponse response { get; set; }
}
[DataContract]
public class CurrencyResponse
{
public CurrencyResponse()
{
this.items = new Dictionary<string,ItemPrices>();
}
[DataMember]
public int success { get; set; }
[DataMember]
public long current_time { get; set; }
[DataMember]
public decimal raw_usd_value { get; set; }
[DataMember]
public string usd_currency { get; set; }
[DataMember]
public long usd_currency_index { get; set; }
[DataMember(EmitDefaultValue = false)]
public Dictionary<string, ItemPrices> items { get; set; }
}
[DataContract]
public class ItemPrices
{
public ItemPrices()
{
this.prices = new Dictionary<long, ItemTradablePrices>();
}
[DataMember(EmitDefaultValue = false)]
public Dictionary<long, ItemTradablePrices> prices { get; set; }
}
[DataContract]
public class ItemTradablePrices
{
[DataMember(EmitDefaultValue = false)]
public ItemCraftablePrices Tradable { get; set; }
// Sometimes appears as "Non-Tradable", sometimes "Untradable". Handle both
[DataMember(EmitDefaultValue = false)]
public ItemCraftablePrices Untradable { get; set; }
[DataMember(Name = "Non-Tradable", EmitDefaultValue=false)]
ItemCraftablePrices NonTradable
{
get
{
return null;
}
set
{
Untradable = value;
}
}
}
[DataContract]
public class ItemCraftablePrices
{
[DataMember(EmitDefaultValue = false)]
[JsonConverter(typeof(PrinceIndexDictionaryConverter))]
public Dictionary<long, PriceIndex> Craftable { get; set; }
// Sometimes appears as "Non-Craftable", sometimes "Uncraftable". Handle both
[DataMember(EmitDefaultValue=false)]
[JsonConverter(typeof(PrinceIndexDictionaryConverter))]
public Dictionary<long, PriceIndex> Uncraftable { get; set; }
[DataMember(Name="Non-Craftable", EmitDefaultValue=false)]
[JsonConverter(typeof(PrinceIndexDictionaryConverter))]
Dictionary<long, PriceIndex> NonCraftable
{
get
{
return null;
}
set
{
Uncraftable = value;
}
}
}
public class PrinceIndexDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Dictionary<long, PriceIndex>);
}
public override bool CanWrite
{
get
{
return false;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var dict = existingValue as Dictionary<long, PriceIndex>;
if (dict == null)
dict = new Dictionary<long, PriceIndex>();
switch (reader.TokenType)
{
case JsonToken.StartArray:
List<PriceIndex> list = new List<PriceIndex>();
serializer.Populate(reader, list);
for (int i = 0; i < list.Count; i++)
dict[i] = list[i];
break;
case JsonToken.StartObject:
serializer.Populate(reader, dict);
break;
default:
Debug.WriteLine("Unexpected token type " + reader.TokenType.ToString());
throw new InvalidOperationException();
}
return dict;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class PriceIndex
{
public string currency { get; set; }
public decimal value { get; set; }
public decimal value_high { get; set; }
public decimal value_raw { get; set; }
public decimal value_high_raw { get; set; }
public long last_update { get; set; }
public decimal difference { get; set; }
}
然后你可以像这样使用它:
public currencyData SendCurrencyQuery()
{
//make call to the API and retrieve JSON data
char[] array2 = { };
using (var client2 = new System.Net.WebClient())
{
client2.Headers.Add("item-data", "application/json");
//get the JSON data.
string currencyJSON = Encoding.UTF8.GetString(client2.UploadData("http://backpack.tf/api/IGetPrices/v4/?key=54972a10b88d885f748b4956&appid=440&compress=1", "POST", Encoding.UTF8.GetBytes(array2)));
//same as above but store itt in currencyData.cs
var currencyData = JsonConvert.DeserializeObject<currencyData>(currencyJSON);
return currencyData;
}
}