Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kiota Serialization cannot deserialize ChangeNotification without TenantId #2447

Closed
AntonioSCoelho opened this issue Apr 19, 2024 · 3 comments
Labels

Comments

@AntonioSCoelho
Copy link

Describe the bug

When using KiotaJsonSerializer.Deserialize to deserialize a ChangeNotification object without TenantId property, the deserializer throws the error: The JSON value could not be converted to System.Guid. Path: $ | LineNumber: 0 | BytePositionInLine: 2.

To generate a ChangeNotification without TenantId, create a Subscription for Calendar events changes using a personal account. Work account works fine.

Expected behavior

Deserialize the string to the Microsoft.Graph.Models.ChangeNotificationCollection model

How to reproduce

// BaseGraphServiceClient ctor
ApiClientBuilder.RegisterDefaultSerializer<JsonSerializationWriterFactory>();
ApiClientBuilder.RegisterDefaultSerializer<TextSerializationWriterFactory>();
ApiClientBuilder.RegisterDefaultSerializer<FormSerializationWriterFactory>();
ApiClientBuilder.RegisterDefaultSerializer<MultipartSerializationWriterFactory>();
ApiClientBuilder.RegisterDefaultDeserializer<JsonParseNodeFactory>();
ApiClientBuilder.RegisterDefaultDeserializer<TextParseNodeFactory>();
ApiClientBuilder.RegisterDefaultDeserializer<FormParseNodeFactory>();

// Notification received from Microsoft Graph Subscription on the "/listen" controller
var stringToDeserialize = "{\"value\":[{\"subscriptionId\":\"fb569d7b-e43f-467a-ae5b-1e23e9e0b11c\",\"subscriptionExpirationDateTime\":\"2024-04-18T16:45:21.3876812+00:00\",\"changeType\":\"updated\",\"resource\":\"Users/1111111111111111/Events/MyEvent=\",\"resourceData\":{\"@odata.type\":\"#Microsoft.Graph.Event\",\"@odata.id\":\"Users/1111111111111111/Events/MyEvent=\",\"@odata.etag\":\"W/\\\"DwAAABYAAAAxYmlTM5oqQIy1293cX+YhAAgJG1wh\\\"\",\"id\":\"AQMkADAwATYwMAItYTBiNC01YjFhLTAwAi0wMAoARgAAAw3iqV3AZapApvPymBx-ImQHADFiaVMzmipAjLXb3dxf5iEAAAIBDQAAADFiaVMzmipAjLXb3dxf5iEACAkrBdAAAAA=\"},\"clientState\":\"8f777b20-9275-4fd7-9a27-8b919aba9907\",\"tenantId\":\"\"}]}";

var value = KiotaJsonSerializer.Deserialize<Microsoft.Graph.Models.ChangeNotificationCollection>(stringToDeserialize);

SDK Version

5.49.0

Latest version known to work for scenario above?

No response

Known Workarounds

No response

Debug output

No response

Configuration

  • OS: Windows 11

Other information

No response

@AntonioSCoelho AntonioSCoelho added status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience labels Apr 19, 2024
@andrueastman
Copy link
Member

Thanks for raising this @AntonioSCoelho

It looks like the Guid parsing is not lenient to empty strings as exists in the payload. At the moment you can probably work around this by writing a converter like below.

    public class JsonGuidConverter : JsonConverter<Guid>
    {
        /// <inheritdoc />
        public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            => reader.TokenType == JsonTokenType.Null
                ? Guid.Empty
                : ReadInternal(ref reader);

        /// <inheritdoc />
        public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options)
            => WriteInternal(writer, value);

        private static Guid ReadInternal(ref Utf8JsonReader reader)
            => string.IsNullOrEmpty(reader.GetString()) ? Guid.Empty : Guid.Parse(reader.GetString()!); // be lenient to empty strings.

        private static void WriteInternal(Utf8JsonWriter writer, Guid value)
            => writer.WriteStringValue(value.ToString("N", CultureInfo.InvariantCulture));
    }

then deserlizing the object as below

        var stringToDeserialize = "{\"value\":[{\"subscriptionId\":\"fb569d7b-e43f-467a-ae5b-1e23e9e0b11c\",\"subscriptionExpirationDateTime\":\"2024-04-18T16:45:21.3876812+00:00\",\"changeType\":\"updated\",\"resource\":\"Users/1111111111111111/Events/MyEvent=\",\"resourceData\":{\"@odata.type\":\"#Microsoft.Graph.Event\",\"@odata.id\":\"Users/1111111111111111/Events/MyEvent=\",\"@odata.etag\":\"W/\\\"DwAAABYAAAAxYmlTM5oqQIy1293cX+YhAAgJG1wh\\\"\",\"id\":\"AQMkADAwATYwMAItYTBiNC01YjFhLTAwAi0wMAoARgAAAw3iqV3AZapApvPymBx-ImQHADFiaVMzmipAjLXb3dxf5iEAAAIBDQAAADFiaVMzmipAjLXb3dxf5iEACAkrBdAAAAA=\"},\"clientState\":\"8f777b20-9275-4fd7-9a27-8b919aba9907\",\"tenantId\":\"\"}]}";
        var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.General)
        {
            Converters = { new JsonGuidConverter() }
        };
        var serializationContext = new Microsoft.Kiota.Serialization.Json.KiotaJsonSerializationContext(serializerOptions);

        using var jsonDocument = JsonDocument.Parse(stringToDeserialize);
        var rootParseNode = new JsonParseNode(jsonDocument.RootElement, serializationContext);

        var value = rootParseNode.GetObjectValue<ChangeNotificationCollection>(ChangeNotificationCollection.CreateFromDiscriminatorValue);

Any chance you'd be willing to submit a PR for the guid parsing to check for empty strings to update the checking at the link below?

https://github.com/microsoft/kiota-serialization-json-dotnet/blob/d3af1f6323032dba0c35976e0c0b12e38a49178b/src/JsonParseNode.cs#L128

@andrueastman andrueastman added Needs: Author Feedback and removed status:waiting-for-triage An issue that is yet to be reviewed or assigned labels Apr 22, 2024
@AntonioSCoelho
Copy link
Author

Thanks for the response. The workaround works for now. I will try to create the PR.

@andrueastman
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants