C# 如何使用字典解析这个JSON?
我正在制作一个需要解析JSON响应的程序。回复中的大部分数据都是无用的,但我需要用它做一些事情C# 如何使用字典解析这个JSON?,c#,json,json.net,steam,steam-web-api,C#,Json,Json.net,Steam,Steam Web Api,我正在制作一个需要解析JSON响应的程序。回复中的大部分数据都是无用的,但我需要用它做一些事情 能够从rgInventory部分检索id的搜索,然后获得相应的classid 获取具有此classid的对象的market\u名称 JSON响应(代码片段,以该格式继续): 完整JSON响应: 我认为,由于库存中每个项目的标识符不断变化(即从469449975_0到619638799_0),我必须将其反序列化到字典中 以下是我迄今为止的代码: namespace SteamTrade { pu
rgInventory
部分检索id
的搜索,然后获得相应的classid
classid的对象的market\u名称
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;
}
}
}
这将返回一个错误,说明序列中没有项目。您正试图将其反序列化到
字典中,这显然失败,因为您有无法反序列化到项目的元素,并且在第一个元素上失败,即成功:true
你有两种方法可以继续
var result=(动态)Newtonsoft.Json.JsonConvert.DeserializeObject(响应)代码>
在这种情况下,可以将结果作为动态对象进行处理
定义并使用与您尝试反序列化的json格式相对应的类
您真正要做的是查询JSON。为此,可以使用DixonD建议的动态对象对其进行反序列化,然后遍历动态对象以找到所需的信息
另一个更简单、更简洁的解决方案是使用类似于XPath for JSON的库来查询JSON。有一个例子可以说明如何做这样的事情。根据,您在问题中发布的JSON无效。但是,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; }
}
要从classid创建市场名称,可以执行以下操作
var classidToDescription = response.rgDescriptions.ToLookup(pair => pair.Value.classid);
这将找到给定classid
的所有rgDescription
类
如果您确定给定的classid
只有一个rgDescription
,则可以执行以下操作:
var classidToDescriptionDictionary = response.rgDescriptions.ToDictionary(pair => pair.Value.classid);
请注意,如果多个描述具有相同的类id,则这将抛出一个带有消息“已添加具有相同密钥的项”的ArgumentException
更新
要从market\u name
转到id
,您需要反转字典并创建反向查找表。因此:
如果您需要回复中的所有市场名称,请执行以下操作:
var marketNames = response.rgDescriptions.Values.Select(d => d.market_name);
var ids = response.rgInventory.Keys;
如果您需要响应中的所有ID,请执行以下操作:
var marketNames = response.rgDescriptions.Values.Select(d => d.market_name);
var ids = response.rgInventory.Keys;
要从market\u 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();
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; }
}
}
给出输出
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
假设我使用您建议的第一种方法,那么我如何继续获得所需的功能?(在我的帖子顶部声明)既然有了市场名称,我就可以让classid有效地反向操作?你是说你想知道我是如何创建数据模型的,如何使用字段rgInventory
,或者如何使用response.rgDescriptions.ToLookup
的返回值?我这方面的问题很糟糕。我需要创建一个方法,该方法可以从market_Names获取rgInventory部分中的“id”。如果您想从market_name
转到id
,那么?@JedBoffey-更新答案。这就是你需要的吗?
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