如何用Newtonsoft.Json反序列化带键嵌套JObject为实体列表
解决方案:将动态键的JSON反序列化为带Name字段的列表
这里有两种实用方案,帮你用Newtonsoft.Json实现需求——把JSON中作为键的币种名称自动存入实体的Name字段,同时转换成列表类型:
方案一:手动转换字典到列表(简单直接)
首先,我们需要调整你的响应类,把Coins定义为Dictionary<string, WhatToMineCalculatorResponse>,因为JSON里的coins本质是一个键值对集合:
internal class WhatToMineCalculatorsResponse { [JsonProperty("coins")] public Dictionary<string, WhatToMineCalculatorResponse> Coins { get; set; } } internal class WhatToMineCalculatorResponse { // 用于存储币种名称的字段 public string Name { get; set; } [JsonProperty("id")] public int Id { get; set; } [JsonProperty("tag")] public string Symbol { get; set; } [JsonProperty("status")] public string Status { get; set; } [JsonProperty("algorithm")] public string Algo { get; set; } [JsonProperty("listed")] public bool IsListed { get; set; } // 记得补充JSON里的其他字段,比如lagging、testing等 [JsonProperty("lagging")] public bool IsLagging { get; set; } [JsonProperty("testing")] public bool IsTesting { get; set; } }
反序列化后,只需要遍历字典,把键赋值给每个实体的Name,再转成列表即可:
// 假设你已经获取到API返回的JSON字符串 string jsonContent = /* 从接口获取的JSON */; // 反序列化为带字典的响应对象 var rawResponse = JsonConvert.DeserializeObject<WhatToMineCalculatorsResponse>(jsonContent); // 转换为带Name字段的列表 var coinList = rawResponse.Coins.Select(kv => { kv.Value.Name = kv.Key; return kv.Value; }).ToList();
这种方法的优势是代码少、易理解,适合快速实现需求。
方案二:自定义JsonConverter(优雅自动化)
如果希望反序列化过程更自动化,不用每次手动转换字典,可以自定义一个JsonConverter,让Newtonsoft.Json自动帮你完成键到Name字段的赋值:
第一步:创建自定义转换器
public class CoinListConverter : JsonConverter<IList<WhatToMineCalculatorResponse>> { public override IList<WhatToMineCalculatorResponse> ReadJson(JsonReader reader, Type objectType, IList<WhatToMineCalculatorResponse> existingValue, bool hasExistingValue, JsonSerializer serializer) { // 先把JSON对象反序列化为字典 var coinDictionary = serializer.Deserialize<Dictionary<string, WhatToMineCalculatorResponse>>(reader); // 将字典键赋值给实体Name,再转成列表 return coinDictionary.Select(kv => { kv.Value.Name = kv.Key; return kv.Value; }).ToList(); } public override void WriteJson(JsonWriter writer, IList<WhatToMineCalculatorResponse> value, JsonSerializer serializer) { // 如果需要把列表序列回JSON对象,这里可以把列表转回字典 var coinDictionary = value.ToDictionary(coin => coin.Name, coin => coin); serializer.Serialize(writer, coinDictionary); } }
第二步:给响应类的Coins属性添加转换器特性
internal class WhatToMineCalculatorsResponse { [JsonProperty("coins")] // 指定使用我们自定义的转换器 [JsonConverter(typeof(CoinListConverter))] public IList<WhatToMineCalculatorResponse> Coins { get; set; } } // 实体类和方案一一致,记得补充所有需要的字段 internal class WhatToMineCalculatorResponse { public string Name { get; set; } [JsonProperty("id")] public int Id { get; set; } [JsonProperty("tag")] public string Symbol { get; set; } [JsonProperty("status")] public string Status { get; set; } [JsonProperty("algorithm")] public string Algo { get; set; } [JsonProperty("listed")] public bool IsListed { get; set; } [JsonProperty("lagging")] public bool IsLagging { get; set; } [JsonProperty("testing")] public bool IsTesting { get; set; } }
第三步:直接反序列化即可
string jsonContent = /* 从接口获取的JSON */; var response = JsonConvert.DeserializeObject<WhatToMineCalculatorsResponse>(jsonContent); // 此时response.Coins已经是每个Item都包含Name字段的列表了 foreach (var coin in response.Coins) { Console.WriteLine($"币种名称:{coin.Name},符号:{coin.Symbol}"); }
这种方案的优势是一次定义,后续反序列化代码非常简洁,适合需要多次处理这类JSON的场景。
内容的提问来源于stack exchange,提问作者shtse8
相关产品推荐
相关产品推荐

