如何遍历Gate.io API返回JObject中的币种键与对应值?
如何规范遍历Gate.io API返回的JObject中的币种键值对?
问题背景
我从Gate.io交易接口拿到了包含账户余额的JSON数据,想要遍历available字段下的各币种名称和对应的可用余额。原始JSON数据如下:
{ "result": "true", "available": { "BTC": "0.83337671", "LTC": "94.364", "ETH": "0.07161", "ETC": "82.35029899" }, "locked": { "BTC": "0.0002", "YAC": "10.01" } }
我尝试用Newtonsoft.Json的JObject解析,但遍历的时候遇到了问题:
var coinData = JObject.Parse(@"{ ""result"": ""true"", ""available"": { ""BTC"": ""0.83337671"", ""LTC"": ""94.364"", ""ETH"": ""0.07161"", ""ETC"": ""82.35029899"" }, ""locked"": { ""BTC"": ""0.0002"", ""YAC"": ""10.01"" } }")["available"]; foreach (JToken item in coinData) { // 这里发现JToken没法直接访问Key属性,不知道怎么正确解析 }
后来我临时用字符串分割的方法解决了,但总觉得不够规范:
foreach (JToken item in coinData) { var data = item.ToString().Replace("\"", String.Empty).Split(':'); // data[0]是币种名称,data[1]是余额 }
想请教有没有更规范的实现方式?
规范的解决方法
其实你遇到的问题核心是没搞清楚JToken的实际类型——available是一个JSON对象,里面的每个子项都是JProperty类型(而不是普通的JToken)。下面给你几种更健壮、更符合.NET编码规范的方法:
方法1:直接遍历JProperty(最直接)
你可以明确指定遍历的是JProperty类型,这样就能直接获取到键(币种名)和值(余额):
// 假设jsonString是你从API拿到的原始JSON字符串 var jObject = JObject.Parse(jsonString); var availableBalances = jObject["available"]; foreach (JProperty prop in availableBalances.Children<JProperty>()) { string coinSymbol = prop.Name; // 比如BTC、LTC string balanceStr = prop.Value.ToString(); // 余额字符串 // 如果需要数值类型,建议用decimal(避免浮点精度问题) if (decimal.TryParse(balanceStr, out decimal balance)) { // 在这里处理数值类型的余额,比如存入数据库或展示 Console.WriteLine($"币种:{coinSymbol},可用余额:{balance}"); } }
方法2:转为Dictionary类型(更灵活)
如果你习惯用字典的方式操作,可以直接把available字段转成Dictionary<string, string>或者Dictionary<string, decimal>:
var jObject = JObject.Parse(jsonString); // 转成字符串字典 var availableStrDict = jObject["available"].ToObject<Dictionary<string, string>>(); foreach (var kvp in availableStrDict) { Console.WriteLine($"币种:{kvp.Key},余额:{kvp.Value}"); } // 直接转成decimal字典(更省心,适合需要数值计算的场景) var availableDecimalDict = jObject["available"].ToObject<Dictionary<string, decimal>>(); foreach (var kvp in availableDecimalDict) { Console.WriteLine($"币种:{kvp.Key},余额:{kvp.Value:N8}"); // 格式化显示8位小数 }
方法3:定义实体类序列化(推荐长期项目)
如果你的项目经常需要处理这类余额数据,建议定义对应的实体类,这样代码可读性和可维护性会高很多:
// 定义实体类,JsonProperty属性对应JSON字段名 public class WalletBalanceResponse { [JsonProperty("result")] public string Result { get; set; } [JsonProperty("available")] public Dictionary<string, decimal> AvailableBalances { get; set; } [JsonProperty("locked")] public Dictionary<string, decimal> LockedBalances { get; set; } } // 解析时直接转成实体类 var response = JsonConvert.DeserializeObject<WalletBalanceResponse>(jsonString); // 遍历可用余额 foreach (var kvp in response.AvailableBalances) { Console.WriteLine($"币种:{kvp.Key},可用余额:{kvp.Value}"); } // 遍历锁定余额也一样 foreach (var kvp in response.LockedBalances) { Console.WriteLine($"币种:{kvp.Key},锁定余额:{kvp.Value}"); }
为什么不推荐字符串分割的方法?
你之前的字符串分割方法虽然能临时解决问题,但存在很多隐患:
- 如果JSON格式发生变化(比如余额值里包含冒号或引号),代码会直接失效;
- 需要自己处理字符串转数值的逻辑,容易出现格式错误;
- 代码可读性差,其他开发者接手时需要花时间理解你的自定义逻辑。
上面的几种方法都是基于Newtonsoft.Json的原生API,能更好地处理JSON的各种边界情况,也更符合.NET的编码规范。
内容的提问来源于stack exchange,提问作者Waleed
相关产品推荐
相关产品推荐

