调用Ethplorer.io API后,如何将TokenInfo的Price转为C#字典?
解决Ethplorer API Price字段反序列化的类型兼容问题
这种同一个字段同时返回布尔值(无价格)和对象(有价格)的API设计确实有点棘手,不过咱们有几种靠谱的解决方案,按类型安全程度给你列出来:
方案1:自定义JsonConverter(最推荐,类型安全)
这个方法能让反序列化过程自动处理两种情况,把Price转换成强类型对象或者字典,完全不用手动判断。
步骤1:定义Price的强类型类(可选,比字典更安全)
如果你知道Price字段的具体结构,先定义一个对应类:
public class PriceData { public double? Rate { get; set; } public string Currency { get; set; } public double? Diff { get; set; } // 其他API返回的价格字段都可以加上 }
步骤2:编写自定义转换器
这个转换器会在反序列化时判断JSON token类型,自动处理布尔值和对象的情况:
public class PriceConverter : JsonConverter { public override bool CanConvert(Type objectType) { // 这里指定要转换的目标类型,比如PriceData或者Dictionary<string, object> return objectType == typeof(PriceData); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 如果是布尔值且为false,直接返回null表示无价格 if (reader.TokenType == JsonToken.Boolean && (bool)reader.Value == false) { return null; } // 如果是对象,正常反序列化为目标类型 return serializer.Deserialize(reader, objectType); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 序列化时如果Price为null,就输出false,否则输出对象 if (value == null) { writer.WriteValue(false); } else { serializer.Serialize(writer, value); } } }
步骤3:修改TokenInfo类的Price属性
给Price属性加上转换器特性,指定用咱们写的转换器:
public class TokenInfo { // 其他自动生成的属性... [JsonConverter(typeof(PriceConverter))] public PriceData Price { get; set; } // 要是想用字典的话,改成下面这样: // [JsonConverter(typeof(PriceConverter))] // public Dictionary<string, object> Price { get; set; } }
之后再用JsonConvert.DeserializeObject<TokenInfo>(rawJSON)反序列化,Price字段会自动处理:无价格时为null,有价格时就是完整的PriceData对象/字典。
方案2:用JObject临时转换(快速灵活,无需修改类)
如果不想写转换器,也可以利用Newtonsoft.Json的JObject来处理自动生成的object类型Price:
var tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(rawJSON); if (tokenInfo.Price is bool) { // 无价格逻辑 Console.WriteLine("该代币暂无价格信息"); } else { // 把object转成JObject,再提取数据 var priceJObj = (JObject)tokenInfo.Price; var rate = priceJObj["rate"].Value<double>(); var currency = priceJObj["currency"].Value<string>(); // 或者直接转成PriceData类 var priceData = priceJObj.ToObject<PriceData>(); }
方案3:dynamic类型快速验证(适合临时测试)
如果只是快速验证API数据,不想改类也不想写转换器,可以用dynamic:
var rawResult = JsonConvert.DeserializeObject<dynamic>(rawJSON); foreach (var token in rawResult.tokens) { if (token.Price is bool && (bool)token.Price == false) { Console.WriteLine("无价格"); } else { // 转成字典或强类型 var priceDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(token.Price.ToString()); Console.WriteLine($"当前价格:{priceDict["rate"]} {priceDict["currency"]}"); } }
缺点是没有编译时类型检查,容易写错字段名,适合临时场景。
内容的提问来源于stack exchange,提问作者Dough
相关产品推荐
相关产品推荐

