我正在制作一个需要解析JSON响应的程序。响应中的大多数数据都没用,但我需要用它来做一些事情。
id
部分检索rgInventory
的搜索,然后获取相应的classid
market_name
classid
醇>
JSON响应(摘录,它继续使用该格式):
{
"success":true,
"rgInventory":{
"1482735510":{
"id":"1482735510",
"classid":"469449975",
"instanceid":"0",
"amount":"1",
"pos":1
},
"1468698711":{
"id":"1468698711",
"classid":"619638799",
"instanceid":"0",
"amount":"1",
"pos":2
},
},
"rgCurrency":[
],
"rgDescriptions":{
"469449975_0":{
"appid":"730",
"classid":"469449975",
"instanceid":"0",
"icon_url":"fWFc82js0fmoRAP-qOIPu5THSWqfSmTELLqcUywGkijVjZYMUrsm1j-9xgEObwgfEh_nvjlWhNzZCveCDfIBj98xqodQ2CZknz5oM7bgZghmfzvDE61HY-Yy_QbpNis77893GtbmoLpffljq4tCXNLN9ZY0fSZPVCaWPZQ_5v0tshKIJK5KBqSjs2i73ejBdAx_EB8I",
"icon_url_large":"fWFc82js0fmoRAP-qOIPu5THSWqfSmTELLqcUywGkijVjZYMUrsm1j-9xgEObwgfEh_nvjlWhNzZCveCDfIBj98xqodQ2CZknz5oM7bgZghmfzvDE61HY-Yy_QbpNis77893a9u35bwDZ13vs9PPNOQpZoodGMOBD6PVMFr4uRgxg6dZepXdpCm72SrhM2wJXBD1ujVT-Ntzxu8",
"icon_drag_url":"",
"name":"SG 553 | Army Sheen",
"market_hash_name":"SG 553 | Army Sheen (Factory New)",
"market_name":"SG 553 | Army Sheen (Factory New)",
"name_color":"D2D2D2",
"background_color":"",
"type":"Consumer Grade Rifle",
"tradable":1,
"marketable":1,
"commodity":0,
"descriptions":[
{
"type":"html",
"value":"Exterior: Factory New"
},
{
"type":"html",
"value":"The Bank Collection",
"color":"9da1a9",
"app_data":{
"def_index":"65535",
"is_itemset_name":1
}
},
],
"actions":[
{
"name":"Inspect in Game...",
"link":"steam:\/\/rungame\/730\/76561202255233023\/+csgo_econ_action_preview%20S%owner_steamid%A%assetid%D2486209296654018845"
}
],
"market_actions":[
{
"name":"Inspect in Game...",
"link":"steam:\/\/rungame\/730\/76561202255233023\/+csgo_econ_action_preview%20M%listingid%A%assetid%D2486209296654018845"
}
],
"tags":[
{
"internal_name":"CSGO_Type_Rifle",
"name":"Rifle",
"category":"Type",
"category_name":"Type"
},
{
"internal_name":"weapon_sg556",
"name":"SG 553",
"category":"Weapon",
"category_name":"Weapon"
},
]
}
}
}
完整的JSON响应:http://steamcommunity.com/id/Mambocsgoshack/inventory/json/730/2/
我相信,因为广告资源中每个项目的标识符都在不断变化(例如469449975_0
到619638799_0
),我必须将其反序列化为字典。
到目前为止,这是我的代码:
namespace SteamTrade
{
public class CSGOInventory
{
public static CSGOInventory FetchInventory(string steamId)
{
WebClient client = new WebClient();
var url = "http://steamcommunity.com/profiles/" + steamId + "/inventory/json/730/2/";
string response = client.DownloadString(url);
Dictionary<string, Item> result = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, Item>>(response);
return new CSGOInventory(result);
}
public Item[] Items { get; set; }
public bool IsPrivate { get; private set; }
public bool IsGood { get; private set; }
protected CSGOInventory(Dictionary<string, Item> apiInventory)
{
for (int i = 0; i < apiInventory.Count; i++)
{
Items[i] = apiInventory.Values.ElementAt(i);
}
}
/*public Item GetItem(int id)
{
return (Items == null ? null : Items.FirstOrDefault(item => item.instanceid == id));
}
public List<Item> GetItemsByDefindex(int defindex)
{
return Items.Where(item => item.def_index == defindex).ToList();
}*/
public class Item
{
public string AppId = "730";
public string ContextId = "2";
[JsonProperty("instanceid")]
public string instanceid { get; set; }
[JsonProperty("market_name")]
public string market_name { get; set; }
[JsonProperty("def_index")]
public string def_index { get; set; }
}
protected class InventoryResult
{
public Item[] items { get; set; }
}
protected class InventoryResponse
{
public InventoryResult result;
}
}
}
我相信我将字典项添加到Items数组完全错误,但无法找出正确的解决方案。
但是,目前的错误是:
将值True转换为类型'SteamTrade.CSGOInventory + Item,路径'成功',第1行,第15位。
我理解这意味着什么,但不知道如何解决它。我不认为我必须定义JSON在我的对象中返回的每个属性,但我可能错了。无论哪种方式,由于JSON的格式从rgInventory
更改为rgDescriptions
部分更改,我不知道如何解决此问题。谁能解释一下如何做到这一点?
更新:
从market_name检索instanceid的方法如下:
public string getInstanceIdFromMarketName(string name)
{
var classIdToId = inventory.rgInventory.ToLookup(pair => pair.Value.classid, pair => pair.Key);
var marketNameToId = inventory.rgDescriptions
.SelectMany(pair => classIdToId[pair.Value.classid].Select(id => new KeyValuePair<string, string>(pair.Value.market_name, id)))
.ToLookup(pair => pair.Key, pair => pair.Value);
if (marketNameToId[name].First() != null)
{
string idForMarket = marketNameToId[name].FirstOrDefault();
return idForMarket;
}
else
{
return null;
}
}
这会返回错误消息,说明序列中没有任何项目。
答案 0 :(得分:2)
根据http://jsonformatter.curiousconcept.com/,您在问题中发布的JSON无效。但是,your link处的JSON是可以的,所以让我们继续。
您想要的信息可以建模为包含两个词典的类:
public class rgInventoryItem
{
public string id { get; set; }
public string classid { get; set; }
}
public class rgDescription
{
public string classid { get; set; }
public string market_name { get; set; }
}
public class InventoryResponse
{
public Dictionary<string, rgInventoryItem> rgInventory { get; set; }
public Dictionary<string, rgDescription> rgDescriptions { get; set; }
}
然后,要从JSON字符串加载,请使用:
var response = JsonConvert.DeserializeObject<InventoryResponse>(json);
但是,rgDescriptions
字典没有直接在classid
上编入索引,而是以某种方式将密钥与classid
相关联,例如
"469449975_0":{
"classid":"469449975",
"market_name":"SG 553 | Army Sheen (Factory New)",
要从classid为市场名称创建lookup,您可以执行
var classidToDescription = response.rgDescriptions.ToLookup(pair => pair.Value.classid);
这将找到给定rgDescription
的所有classid
个类。
如果您确定,给定rgDescription
只有一个classid
,您可以这样做:
var classidToDescriptionDictionary = response.rgDescriptions.ToDictionary(pair => pair.Value.classid);
请注意,这会向ArgumentException
发送消息&#34;已添加具有相同密钥的项目&#34;如果多个描述具有相同的类ID。
<强>更新强>
要从market_name
转到id
,您需要反转字典并创建反向查找表。因此:
如果您需要回复中的所有市场名称,请执行以下操作:
var marketNames = response.rgDescriptions.Values.Select(d => d.market_name);
如果您需要响应中的所有ID,请执行以下操作:
var ids = response.rgInventory.Keys;
从market_name
映射到id
,首先创建反向查找:
var classIdToId = response.rgInventory.ToLookup(pair => pair.Value.classid, pair => pair.Key);
var marketNameToId = response.rgDescriptions
.SelectMany(pair => classIdToId[pair.Value.classid].Select(id => new KeyValuePair<string, string>(pair.Value.market_name, id)))
.ToLookup(pair => pair.Key, pair => pair.Value);
要获取引用给定市场名称的所有 ID,请执行以下操作:
var idsForMarket = marketNameToId[name].ToList();
要获取引用给定市场名称的第一个 ID,请执行以下操作:
var firstIdForMarket = marketNameToId[name].FirstOrDefault();
更新2
以下是您的课程的修改版本:
public class rgInventoryItem
{
public string id { get; set; }
public string classid { get; set; }
}
public class rgDescription
{
public string classid { get; set; }
public string market_name { get; set; }
}
public class CSGOInventory
{
public static CSGOInventory FetchInventory(string steamId)
{
var url = "http://steamcommunity.com/profiles/" + steamId + "/inventory/json/730/2/";
return FetchInventoryFromUrl(new Uri(url));
}
public static CSGOInventory FetchInventoryFromUrl(Uri url)
{
using (WebClient client = new WebClient())
{
string response = client.DownloadString(url);
var inventory = JsonConvert.DeserializeObject<InventoryResponse>(response);
return new CSGOInventory(inventory);
}
}
readonly InventoryResponse inventory;
readonly ILookup<string, string> classIdToId;
readonly ILookup<string, string> marketNameToId;
CSGOInventory(InventoryResponse inventory)
{
if (inventory == null)
throw new ArgumentNullException();
this.inventory = inventory;
this.classIdToId = inventory.rgInventory.ToLookup(pair => pair.Value.classid, pair => pair.Key);
this.marketNameToId = inventory.rgDescriptions
.SelectMany(pair => classIdToId[pair.Value.classid].Select(id => new KeyValuePair<string, string>(pair.Value.market_name, id)))
.ToLookup(pair => pair.Key, pair => pair.Value);
}
public IDictionary<string, rgInventoryItem> InventoryItems { get { return this.inventory == null ? null : this.inventory.rgInventory; } }
public IDictionary<string, rgDescription> InventoryDescriptions { get { return this.inventory == null ? null : this.inventory.rgDescriptions; } }
public IEnumerable<string> MarketNames { get { return InventoryDescriptions == null ? null : InventoryDescriptions.Values.Select(d => d.market_name); } }
public IEnumerable<string> InventoryIds { get { return InventoryItems == null ? null : InventoryItems.Keys; } }
public string getInstanceIdFromMarketName(string name)
{
return marketNameToId[name].FirstOrDefault();
}
public IEnumerable<string> getInstanceIdsFromMarketName(string name)
{
return marketNameToId[name];
}
class InventoryResponse
{
public Dictionary<string, rgInventoryItem> rgInventory { get; set; }
public Dictionary<string, rgDescription> rgDescriptions { get; set; }
}
}
使用它,以下测试类:
public static class TestClass
{
public static void Test()
{
//string url = @"d:\temp\question28328432.json";
string url = @"http://steamcommunity.com/id/Mambocsgoshack/inventory/json/730/2/";
var inventory = CSGOInventory.FetchInventoryFromUrl(new Uri(url));
foreach (var market in inventory.MarketNames)
{
Console.WriteLine(string.Format(" Market {0,-50}: id {1}", market, inventory.getInstanceIdFromMarketName(market)));
}
}
}
给出输出
Market SG 553 | Army Sheen (Factory New) : id 1482735510
Market Offer | Music Kit | Noisia, Sharpened : id 1468698711
Market Offer | Sticker | Bomb Squad (Foil) : id 1468698710
Market Offer | Sticker | Dinked : id 1468698709
Market Offer | Sticker | Kawaii Killer CT : id 1468698708
Market Operation Breakout Weapon Case : id 1462270322
Market Operation Vanguard Weapon Case : id 1459818809
Market M4A4 | Howl (Minimal Wear) : id 1450750270
Market Operation Phoenix Weapon Case : id 1391297747
Market Negev | Army Sheen (Minimal Wear) : id 1370560151
Market Huntsman Weapon Case : id 1305163655
Market Tec-9 | Army Mesh (Minimal Wear) : id 1304896559
Market Galil AR | Cerberus (Well-Worn) : id 1214784536
Market StatTrakT Tec-9 | Sandstorm (Field-Tested) : id 1201208194
Market G3SG1 | Contractor (Field-Tested) : id 1189828757
Market Campaign Vanguard : id 1103736871
Market Campaign Weapons Specialist : id 1103736870
Market Operation Vanguard Challenge Coin : id 1103736869
Market StatTrakT XM1014 | Red Python (Field-Tested) : id 957595359
Market StatTrakT CZ75-Auto | Hexane (Field-Tested) : id 814442137
Market Negev | Army Sheen (Factory New) : id 623936007
Market SSG 08 | Sand Dune (Well-Worn) : id 616381102
Market Silver Operation Breakout Coin : id 612997861
Market UMP-45 | Scorched (Field-Tested) : id 603041123
答案 1 :(得分:1)
您要做的是查询您的JSON。为此,您可以使用DixonD提议的动态对象对其进行反序列化,然后遍历动态对象以查找所需的信息。
另一个更简单,更简洁的解决方案是使用像jsonpath这样的库来查询您的JSON,这类似于XPath for JSON。有关如何执行此类操作的示例here。
答案 2 :(得分:0)
您正在尝试将其反序列化为Dictionary<string, Item>
,这显然会失败,因为您的元素无法反序列化为Item
,并且在第一个"success": true
上失败}
您有几种方法可以继续。
var result = (dynamic)Newtonsoft.Json.JsonConvert.DeserializeObject(response);
在这种情况下,您可以将结果作为动态对象处理。
定义并使用与您尝试反序列化的json格式相对应的类。