You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 05:25:12