在C#中使用Newtonsoft.Json动态修改JSON属性名的问题
解决JSON顶层动态数字键的反序列化问题
你的问题核心在于JSON顶层的键是动态变化的数字字符串,而你原来的实体类用了固定的[JsonProperty("158023")]来绑定,这显然无法适配不同的键值。因为JsonProperty是编译时确定的属性,没办法在运行时动态修改它的值。不过我们可以通过调整实体类结构或者直接使用字典类型来解决这个问题,下面给你两种实用的方案:
方案一:直接反序列化为Dictionary<string, Token>
这是最简洁的方式,因为你的JSON本质上就是一个以数字字符串为键、Token对象为值的字典结构,完全可以跳过原来的Prices类,直接反序列化到字典:
// 直接反序列化到字典,不需要原来的Prices类 var tokenMap = JsonConvert.DeserializeObject<Dictionary<string, Token>>(myJson, PriceConverter.Settings); // 如果你需要获取第一个Token(不管键是什么) Token firstToken = tokenMap.Values.FirstOrDefault(); // 如果你知道目标键,比如"158025",直接取值 if (tokenMap.TryGetValue("158025", out Token targetToken)) { // 这里可以使用targetToken.Prices.Xbox、targetToken.Prices.Ps等属性 string xboxLcPrice = targetToken.Prices.Xbox.LcPrice; }
这种方式不需要修改你原来定义的Token、PricesClass、Pc类,直接复用即可,非常高效。
方案二:用JsonExtensionData收集动态键
如果你还是想保留Prices类的结构,可以使用Newtonsoft.Json提供的[JsonExtensionData]特性,把所有动态的顶层键值对收集到一个字典里,再通过方法来获取对应的Token对象:
修改你的Prices类:
public partial class Prices { // 用这个特性收集所有未匹配的顶层键值对 [JsonExtensionData] private Dictionary<string, JToken> _dynamicTokens; // 提供方法来获取指定ID的Token public Token GetToken(string tokenId) { if (_dynamicTokens != null && _dynamicTokens.TryGetValue(tokenId, out var tokenData)) { return tokenData.ToObject<Token>(); } return null; } // 或者获取第一个Token(适用于顶层只有一个键的情况) public Token GetFirstToken() { return _dynamicTokens?.Values.FirstOrDefault()?.ToObject<Token>(); } // 保留原来的FromJson方法 public static Prices FromJson(string json) => JsonConvert.DeserializeObject<Prices>(json, PriceConverter.Settings); }
使用的时候和原来的方式类似,只是多一步获取Token的操作:
Prices prices = Prices.FromJson(myJson); // 获取ID为"158025"的Token Token token = prices.GetToken("158025"); // 或者直接拿第一个Token Token firstToken = prices.GetFirstToken();
为什么原来的方式无法适配?
[JsonProperty]特性是在编译阶段就确定了要绑定的键名,运行时没办法动态修改这个属性的参数值。所以面对动态变化的键名,我们必须使用支持动态键的数据结构(比如Dictionary)或者借助框架提供的扩展数据特性来处理。
内容的提问来源于stack exchange,提问作者MKiperszmid
相关产品推荐
相关产品推荐

