diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEvent.cs b/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEvent.cs index 3e29b5573463..bfae320ed8ec 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEvent.cs +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEvent.cs @@ -3,12 +3,14 @@ using System; using System.Text.Json; +using System.Text.Json.Serialization; using Azure.Core; using Azure.Messaging.EventGrid.Models; namespace Azure.Messaging.EventGrid { /// Properties of an event published to an Event Grid topic using the EventGrid Schema. + [JsonConverter(typeof(EventGridEventConverter))] public class EventGridEvent { /// Initializes a new instance of . diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEventConverter.cs b/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEventConverter.cs new file mode 100644 index 000000000000..7fc9a57ca619 --- /dev/null +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridEventConverter.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core; +using Azure.Messaging.EventGrid.Models; + +namespace Azure.Messaging.EventGrid +{ + /// + /// A custom converter that attributes the type. + /// This allows System.Text.Json to serialize and deserialize EventGridEvent by default. + /// + internal class EventGridEventConverter : JsonConverter + { + /// + /// Gets or sets the serializer to use for the data portion of the . If not specified, + /// JsonObjectSerializer is used. + /// + /// + public override EventGridEvent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + JsonDocument requestDocument = JsonDocument.ParseValue(ref reader); + return new EventGridEvent(EventGridEventInternal.DeserializeEventGridEventInternal(requestDocument.RootElement)); + } + + /// + public override void Write(Utf8JsonWriter writer, EventGridEvent value, JsonSerializerOptions options) + { + JsonDocument data = JsonDocument.Parse(value.Data.ToStream()); + var eventGridEventInternal = new EventGridEventInternal( + value.Id, + value.Subject, + data.RootElement, + value.EventType, + value.EventTime, + value.DataVersion) + { + Topic = value.Topic + }; + ((IUtf8JsonSerializable) eventGridEventInternal).Write(writer); + } + } +} diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridPublisherClient.cs b/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridPublisherClient.cs index ee0e90bda91d..04e0896e8afa 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridPublisherClient.cs +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/src/Customization/EventGridPublisherClient.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using Azure.Core; using Azure.Core.Pipeline; -using Azure.Messaging.EventGrid.Models; namespace Azure.Messaging.EventGrid { @@ -160,26 +159,9 @@ private async Task SendEventsInternal(IEnumerable even using HttpMessage message = _pipeline.CreateMessage(); Request request = CreateEventRequest(message, "application/json"); - var content = new Utf8JsonRequestContent(); - content.JsonWriter.WriteStartArray(); - foreach (EventGridEvent egEvent in events) - { - JsonDocument data = JsonDocument.Parse(egEvent.Data.ToStream()); - EventGridEventInternal newEGEvent = new EventGridEventInternal( - egEvent.Id, - egEvent.Subject, - data.RootElement, - egEvent.EventType, - egEvent.EventTime, - egEvent.DataVersion) - { - Topic = egEvent.Topic - }; - content.JsonWriter.WriteObjectValue(newEGEvent); - } - content.JsonWriter.WriteEndArray(); - request.Content = content; + // leverage custom converter for EventGridEvent + request.Content = RequestContent.Create(JsonSerializer.Serialize(events)); if (async) { diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/tests/ConsumeEventTests.cs b/sdk/eventgrid/Azure.Messaging.EventGrid/tests/ConsumeEventTests.cs index 6b87784c27cc..239e1c8c8508 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/tests/ConsumeEventTests.cs +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/tests/ConsumeEventTests.cs @@ -31,6 +31,21 @@ public void ParsesEventGridEnvelope() Assert.AreEqual("1", egEvent.DataVersion); } + [Test] + public void ParsesEventGridEnvelopeUsingConverter() + { + string requestContent = "[{ \"id\": \"2d1781af-3a4c-4d7c-bd0c-e34b19da4e66\", \"topic\": \"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\", \"subject\": \"mySubject\", \"data\": { \"validationCode\": \"512d38b6-c7b8-40c8-89fe-f46f9e9622b6\", \"validationUrl\": \"https://rp-eastus2.eventgrid.azure.net:553/eventsubscriptions/estest/validate?id=B2E34264-7D71-453A-B5FB-B62D0FDC85EE&t=2018-04-26T20:30:54.4538837Z&apiVersion=2018-05-01-preview&token=1BNqCxBBSSE9OnNSfZM4%2b5H9zDegKMY6uJ%2fO2DFRkwQ%3d\" }, \"eventType\": \"Microsoft.EventGrid.SubscriptionValidationEvent\", \"eventTime\": \"2018-01-25T22:12:19.4556811Z\", \"metadataVersion\": \"1\", \"dataVersion\": \"1\"}]"; + + EventGridEvent[] events = JsonSerializer.Deserialize(requestContent); + var egEvent = events[0]; + Assert.AreEqual("/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", egEvent.Topic); + Assert.AreEqual("2d1781af-3a4c-4d7c-bd0c-e34b19da4e66", egEvent.Id); + Assert.AreEqual("mySubject", egEvent.Subject); + Assert.AreEqual(SystemEventNames.EventGridSubscriptionValidation, egEvent.EventType); + Assert.AreEqual(DateTimeOffset.Parse("2018-01-25T22:12:19.4556811Z"), egEvent.EventTime); + Assert.AreEqual("1", egEvent.DataVersion); + } + [Test] public void ConsumeStorageBlobDeletedEventWithExtraProperty() { @@ -72,6 +87,23 @@ public void ConsumeEventNotWrappedInAnArray() } } + [Test] + public void ConsumeEventNotWrappedInAnArrayWithConverter() + { + string requestContent = "{ \"topic\": \"/subscriptions/id/resourceGroups/Storage/providers/Microsoft.Storage/storageAccounts/xstoretestaccount\", \"subject\": \"/blobServices/default/containers/testcontainer/blobs/testfile.txt\", \"eventType\": \"Microsoft.Storage.BlobDeleted\", \"eventTime\": \"2017-11-07T20:09:22.5674003Z\", \"id\": \"4c2359fe-001e-00ba-0e04-58586806d298\", \"data\": { \"api\": \"DeleteBlob\", \"requestId\": \"4c2359fe-001e-00ba-0e04-585868000000\", \"contentType\": \"text/plain\", \"blobType\": \"BlockBlob\", \"url\": \"https://example.blob.core.windows.net/testcontainer/testfile.txt\", \"sequencer\": \"0000000000000281000000000002F5CA\", \"brandNewProperty\": \"0000000000000281000000000002F5CA\", \"storageDiagnostics\": { \"batchId\": \"b68529f3-68cd-4744-baa4-3c0498ec19f0\" } }, \"dataVersion\": \"\", \"metadataVersion\": \"1\"}"; + + EventGridEvent egEvent = JsonSerializer.Deserialize(requestContent); + + Assert.NotNull(egEvent); + switch (egEvent.EventType) + { + case SystemEventNames.StorageBlobDeleted: + StorageBlobDeletedEventData blobDeleted = egEvent.Data.ToObjectFromJson(); + Assert.AreEqual("https://example.blob.core.windows.net/testcontainer/testfile.txt", blobDeleted.Url); + break; + } + } + [Test] public void ConsumeMultipleEventsInSameBatch() { diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/tests/EventGridEventTests.cs b/sdk/eventgrid/Azure.Messaging.EventGrid/tests/EventGridEventTests.cs index 6e22b4e28141..612a6f33122a 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/tests/EventGridEventTests.cs +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/tests/EventGridEventTests.cs @@ -140,7 +140,7 @@ public async Task RespectsPortFromUriSendingEventGridEvents() private static List DeserializeRequest(Request request) { - var content = request.Content as Utf8JsonRequestContent; + var content = request.Content; var stream = new MemoryStream(); content.WriteTo(stream, CancellationToken.None); stream.Position = 0;