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

Graph API读取日历事件Expand Extensions时JSON解析错误求助

问题:Graph API读取带Open Extensions的日历事件时JSON解析失败

我用C#和Graph API为委派用户创建、读取日历事件,不使用Open Extensions时一切正常。创建带OpenTypeExtension的日历事件代码可成功执行,但读取时取消注释requestConfiguration.QueryParameters.Expand = new string[] { "extensions" };后,无法读取任何事件,抛出JSON解析错误。

创建带OpenTypeExtension的事件代码

var precomExtension = new OpenTypeExtension
{
    OdataType = "microsoft.graph.openTypeExtension",
    ExtensionName = "com.zxcasd.zxcasdExtensions",
    AdditionalData = new Dictionary<string, object>
    {
        {
            "zxcasd" , "1234586"
        }
    }
};

var @event = new Event
{
    Subject = "Kalle Anka",
    Body = new ItemBody
    {
        ContentType = BodyType.Text,
        Content = "This is a test from zxczxc, sorry for any inconvinience it may cause"
    },
    Start = new DateTimeTimeZone
    {
        DateTime = "2025-12-24T14:00:00",
        TimeZone = "Pacific Standard Time"
    },
    End = new DateTimeTimeZone
    {
        DateTime = "2025-12-24T15:00:00",
        TimeZone = "Pacific Standard Time"
    },
    Location = new Location
    {
        DisplayName = "Conference Room"
    },
    Extensions = new List<Extension>
    {
        precomExtension
    },
};

try
{
    await graphClient.Users[userEmail].Events.PostAsync(@event);
    Console.WriteLine("Event created successfully!");
}
catch (ServiceException ex)
{
    Console.WriteLine($"Error creating event: {ex.Message}");
}

读取事件代码(取消注释Expand后报错)

var events3 = await graphServiceClient
    .Users[user]
    .Events
    .GetAsync(requestConfiguration =>
    {
        requestConfiguration.QueryParameters.Select = new string[] { "Id", "Subject", "Start", "End", "Organizer", "createdDateTime", "lastModifiedDateTime" };
        requestConfiguration.QueryParameters.Expand = new string[] { "extensions" };
        requestConfiguration.QueryParameters.Filter = $"start/dateTime ge '{startDateString}' and end/dateTime le '{endDateString}'";
        requestConfiguration.QueryParameters.Orderby = new string[] { $"start/dateTime" };
        requestConfiguration.QueryParameters.Top = 9999;
    });

if (events3?.Value?.Count() > 0)
{
    Console.WriteLine($"Nr of retrived events: {events3.Value.Count}");
    Console.WriteLine("*********************************");
}
foreach (var eventItem in events3.Value)
{
    Console.WriteLine($"Id: {eventItem.Id}");
    Console.WriteLine($"Start: {eventItem.Start.DateTime}");
    Console.WriteLine($"End: {eventItem.End.DateTime}");
    Console.WriteLine($"Subject: {eventItem.Subject}");
    Console.WriteLine($"Organizer: {eventItem.Organizer?.EmailAddress?.Name ?? "No organizer"}");
    Console.WriteLine($"Created: {eventItem.CreatedDateTime}");
    Console.WriteLine($"LastModified: {eventItem.LastModifiedDateTime}");
    Console.WriteLine("*********************************");
}

抛出的错误信息

{"Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. LineNumber: 0 | BytePositionInLine: 437."}
    BytePositionInLine: 437
    Data: {System.Collections.ListDictionaryInternal}
    HResult: -2146233088
    HelpLink: null
    InnerException: null
    LineNumber: 0
    Message: "Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. LineNumber: 0 | BytePositionInLine: 437."
    Path: null
    Source: "System.Text.Json"
    StackTrace: "   at System.Text.Json.Utf8JsonReader.ReadSingleSegment()\r\n   at System.Text.Json.Utf8JsonReader.Read()\r\n   at System.Text.Json.JsonDocument.Parse(ReadOnlySpan`1 utf8JsonSpan, JsonReaderOptions readerOptions, MetadataDb&amp; database, StackRowStack&amp; stack)\r\n   at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory`1 utf8Json, JsonReaderOptions readerOptions, Byte[] extraRentedArrayPoolBytes, PooledByteBufferWriter extraPooledByteBufferWriter)\r\n   at System.Text.Json.JsonDocument.&lt;ParseAsyncCore&gt;d__65.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory.&lt;GetRootParseNodeAsync&gt;d__7.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Kiota.Abstractions.Serialization.ParseNodeProxyFactory.&lt;GetRootParseNodeAsync&gt;d__8.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Kiota.Abstractions.Serialization.ParseNodeFactoryRegistry.&lt;GetRootParseNodeAsync&gt;d__9.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Kiota.Abstractions.Serialization.ParseNodeProxyFactory.&lt;GetRootParseNodeAsync&gt;d__8.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.&lt;GetRootParseNodeAsync&gt;d__30.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.&lt;SendAsync&gt;d__20`1.MoveNext()\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.&lt;SendAsync&gt;d__20`1.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Microsoft.Graph.Users.Item.Events.EventsRequestBuilder.&lt;GetAsync&gt;d__8.MoveNext()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at AzureCalendar.Program.&lt;GetCalendarAppointments&gt;d__5.MoveNext() in E:\_Code_\Testing\AzureCalendar\AzureCalendar\Program.cs:line 229"
    TargetSite: {Boolean ReadSingleSegment()}

问题原因

这个错误的核心是批量扩展所有extensions时,Graph API返回的扩展类型混合(包含系统扩展和自定义扩展),导致Kiota序列化器无法正确解析JSON结构。另外,部分事件没有扩展时,返回的extensions字段为null或空数组,和带有扩展的事件返回结构不一致,进一步加剧了解析冲突。

解决方案

1. 过滤扩展,只获取自定义的OpenTypeExtension

不要直接扩展所有extensions,而是通过$filter指定自定义扩展的ID,这样只会返回目标扩展,避免系统扩展干扰:

requestConfiguration.QueryParameters.Expand = new string[] { "extensions($filter=id eq 'com.zxcasd.zxcasdExtensions')" };

2. 单独获取每个事件的扩展

先读取所有事件,再针对每个事件单独请求扩展,规避批量解析的类型冲突:

foreach (var eventItem in events3.Value)
{
    Console.WriteLine($"Id: {eventItem.Id}");
    Console.WriteLine($"Start: {eventItem.Start.DateTime}");
    // 其他属性输出...

    // 单独获取当前事件的扩展
    var extensions = await graphServiceClient.Users[user].Events[eventItem.Id].Extensions.GetAsync();
    if (extensions?.Value?.Count > 0)
    {
        var customExt = extensions.Value.FirstOrDefault(e => e.Id == "com.zxcasd.zxcasdExtensions") as OpenTypeExtension;
        if (customExt != null)
        {
            Console.WriteLine($"Custom zxcasd value: {customExt.AdditionalData["zxcasd"]}");
        }
    }
    Console.WriteLine("*********************************");
}

3. 升级Graph SDK版本

如果使用的是较旧的Graph SDK v5版本,可能存在Kiota序列化器的bug,升级到最新稳定版可以解决部分解析异常问题。


内容的提问来源于stack exchange,提问作者merger

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:57:34