不能将这个JSON数据存储在c#中?

时间:2015-03-30 19:09:44

标签: c# json json.net

我尝试使用名为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循环则不会打印任何内容。

提前致谢并对不良措辞等表示歉意。 Backpack.tf API doccumentation

1 个答案:

答案 0 :(得分:3)

currencyData存在许多问题:

  1. 返回的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
            },
    
  2. 您有几个声明为int的字段,可以包含小数数据。他们需要更改为其他内容,例如decimal

  3. 您的数据模型与记录的模型不匹配,模型比您的模型深几层。

  4. currencyData的以下代码和对象同时读取了文档中显示的JSON和调用实际返回的JSON,因为我认为两者都必须处理。另请注意文档中的以下qualification

      

    每个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;
            }
        }