如何在C#中从JSON响应提取objectId和displayName?
问题:提取Azure AD用户的objectId和displayName失败
我尝试从下方JSON格式的HTTP请求结果中提取objectId和displayName,但始终未能成功,希望有人能指导我完成这两个字段的提取。
现有代码
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.windows.net/") }; string URI = $"/{TenantID}/users?$filter=userPrincipalName%20eq%20'{EmailAddress}'&api-version=1.6"; httpClient.DefaultRequestHeaders.Remove("Authorization"); httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + MSGraphToken); HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false); var HttpsResponse = await response.Content.ReadAsStringAsync(); dynamic Result = JsonConvert.DeserializeObject<object>(HttpsResponse); UserDetails UserDetailsList = new UserDetails(); dynamic OdataResult = Result["value"]; if (Result != null) { UserDetailsList.DisplayName = OdataResult.displayName ?? "N/A"; UserDetailsList.ObjectID = OdataResult.objectId ?? "N/A"; } return UserDetailsList;
JSON响应结果
{ "value": [ { "odata.type": "Microsoft.DirectoryServices.User", "objectType": "User", "objectId": "00000000-0000-0000-0000-000000000000", "assignedPlans": [ { "assignedTimestamp": "2022-09-06T20:38:49Z", "capabilityStatus": "Enabled", "service": "RMSOnline", "servicePlanId": "00000000-0000-0000-0000-000000000000" }, { "assignedTimestamp": "2022-09-06T20:38:49Z", "capabilityStatus": "Enabled", "service": "Adallom", "servicePlanId": "00000000-0000-0000-0000-000000000000" } ], "displayName": "Sachin Tendulkar (alt_sachint)", "employeeId": "000000", "userPrincipalName": "alt_sachint@pme.gbl.msidentity.com" } ] }
问题原因与解决方案
问题根源
JSON响应中的value是数组类型(即使只有一个用户结果),你的代码直接将Result["value"]当作单个对象访问displayName和objectId,自然会失败——数组本身没有这些属性,属性存在于数组的元素中。
修正方案1:保留dynamic的写法
直接修改代码,先获取数组的第一个元素再提取字段:
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.windows.net/") }; string URI = $"/{TenantID}/users?$filter=userPrincipalName%20eq%20'{EmailAddress}'&api-version=1.6"; httpClient.DefaultRequestHeaders.Remove("Authorization"); httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + MSGraphToken); HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false); var HttpsResponse = await response.Content.ReadAsStringAsync(); dynamic Result = JsonConvert.DeserializeObject<object>(HttpsResponse); UserDetails UserDetailsList = new UserDetails(); // 先判断数组是否存在且有元素 if (Result?.value != null && Result.value.Count > 0) { dynamic user = Result.value[0]; // 取出数组中的第一个用户对象 UserDetailsList.DisplayName = user.displayName ?? "N/A"; UserDetailsList.ObjectID = user.objectId ?? "N/A"; } else { // 未找到用户时的默认值 UserDetailsList.DisplayName = "N/A"; UserDetailsList.ObjectID = "N/A"; } return UserDetailsList;
修正方案2:使用强类型模型(推荐)
定义与JSON结构匹配的实体类,避免dynamic的运行时风险,同时提升代码可读性:
首先定义模型类:
// 对应整个响应结构 public class UserResponse { public List<User> value { get; set; } } // 对应单个用户的结构 public class User { public string objectId { get; set; } public string displayName { get; set; } // 若需要其他字段,可在此添加 } // 你的原有UserDetails类 public class UserDetails { public string DisplayName { get; set; } public string ObjectID { get; set; } }
然后修改请求处理代码:
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.windows.net/") }; string URI = $"/{TenantID}/users?$filter=userPrincipalName%20eq%20'{EmailAddress}'&api-version=1.6"; httpClient.DefaultRequestHeaders.Remove("Authorization"); httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + MSGraphToken); HttpResponseMessage response = await httpClient.GetAsync(URI).ConfigureAwait(false); var HttpsResponse = await response.Content.ReadAsStringAsync(); UserResponse Result = JsonConvert.DeserializeObject<UserResponse>(HttpsResponse); UserDetails UserDetailsList = new UserDetails(); if (Result?.value != null && Result.value.Any()) { var user = Result.value.First(); UserDetailsList.DisplayName = user.displayName ?? "N/A"; UserDetailsList.ObjectID = user.objectId ?? "N/A"; } else { UserDetailsList.DisplayName = "N/A"; UserDetailsList.ObjectID = "N/A"; } return UserDetailsList;
强类型写法的优势:编译阶段就能发现字段名拼写错误,避免dynamic带来的运行时异常,代码维护性更强。
内容的提问来源于stack exchange,提问作者Vinny
相关产品推荐
相关产品推荐

