如何使用Json.NET或其他类库反序列化含动态命名属性的API返回JSON
如何使用Json.NET或其他类库反序列化含动态命名属性的API返回JSON
我太懂你这种困扰了——API返回的JSON里藏着个属性名动态变化的字段,虽然格式固定但后缀ID每次都不一样,常规的类定义根本没法直接映射对吧?我之前也处理过几乎一模一样的场景,用Json.NET完全能搞定,下面给你一步步拆解方案:
1. 先定义基础类结构
首先,咱们先把固定属性和动态属性对应的结构理清楚:
- 那个动态属性里的
__deferred是固定结构,先单独定义一个类:
public class Deferred { public string uri { get; set; } }
- 然后是每个
entry的类,固定属性直接明确定义,动态属性用Json.NET的[JsonExtensionData]特性来承接——这个特性专门用来处理JSON里那些没有对应类属性的“额外”键值对,刚好适配咱们的场景:
public class Entry { // 这些都是固定属性,直接对应JSON里的字段 public string cuid { get; set; } public string name { get; set; } public string description { get; set; } public string id { get; set; } public string type { get; set; } public string ownerid { get; set; } public string updated { get; set; } public string parentid { get; set; } // 用这个字典接收所有动态命名的属性 [JsonExtensionData] public Dictionary<string, JToken> DynamicProperties { get; set; } }
- 最后是整个API返回的根对象,用来包裹
entries数组:
public class ApiResponse { public List<Entry> entries { get; set; } }
2. 执行反序列化操作
有了类结构,反序列化就很简单了,一行代码搞定:
// 把apiResponseJson替换成你实际拿到的API返回字符串 var apiResponse = JsonConvert.DeserializeObject<ApiResponse>(apiResponseJson);
3. 提取动态属性内容
因为你知道动态属性的名字格式是https://bi.com/biprws/v1/documents/{数字ID},咱们可以用正则匹配来精准找到它:
foreach (var entry in apiResponse.entries) { // 匹配符合格式的动态属性键 var documentPropertyKey = entry.DynamicProperties.Keys.FirstOrDefault(key => Regex.IsMatch(key, @"^https://bi.com/biprws/v1/documents/\d+$")); if (documentPropertyKey != null) { // 如果你需要属性里的__deferred内容,就转成Deferred对象 var deferredData = entry.DynamicProperties[documentPropertyKey].ToObject<Deferred>(); Console.WriteLine($"文档URI: {deferredData.uri}"); // 你之前说只要动态属性的名字就够用,那直接取documentPropertyKey就行 Console.WriteLine($"动态属性名称: {documentPropertyKey}"); } }
4. 备选方案:用System.Text.Json(无需额外安装包)
如果你不想用Json.NET,.NET Core/.NET 5+自带的System.Text.Json也能实现,思路差不多,只是类定义和反序列化方法略有不同:
- 把Entry类里的
Dictionary<string, JToken>换成Dictionary<string, JsonElement>,特性还是[JsonExtensionData] - 反序列化用
JsonSerializer.Deserialize<ApiResponse>(apiResponseJson)
另外你提到之前看到的那个关于动态数字键的帖子,虽然它没法完全满足你的场景,但咱们这个方案刚好补上了缺口——既能完整保留所有固定属性的映射,又能灵活处理动态命名的字段,完全适配你的需求。
备注:内容来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

