<PackageReference Include="Azure.Core" Version="1.47.2" />

CloudEventConverter

A custom converter that attributes the CloudEvent type. This allows System.Text.Json to serialize and deserialize CloudEvents by default.
using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization; namespace Azure.Messaging { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("This utilizes reflection-based JSON serialization and deserialization which is not compatible with trimming.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("This utilizes reflection-based JSON serialization and deserialization which is not compatible with trimming.")] internal class CloudEventConverter : JsonConverter<CloudEvent> { public override CloudEvent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using (JsonDocument jsonDocument = JsonDocument.ParseValue(ref reader)) return DeserializeCloudEvent(jsonDocument.RootElement, false); } internal static CloudEvent DeserializeCloudEvent(JsonElement element, bool skipValidation) { CloudEvent cloudEvent = new CloudEvent(); foreach (JsonProperty item in element.EnumerateObject()) { JsonElement element2; if (item.NameEquals("id")) { element2 = item.Value; if (element2.ValueKind != JsonValueKind.Null) { CloudEvent cloudEvent2 = cloudEvent; element2 = item.Value; cloudEvent2.Id = element2.GetString(); } } else if (item.NameEquals("source")) { element2 = item.Value; if (element2.ValueKind != JsonValueKind.Null) { CloudEvent cloudEvent3 = cloudEvent; element2 = item.Value; cloudEvent3.Source = element2.GetString(); } } else if (item.NameEquals("data")) { cloudEvent.Data = new BinaryData((object)item.Value, (JsonSerializerOptions)null, (Type)null); cloudEvent.DataFormat = CloudEventDataFormat.Json; } else if (item.NameEquals("data_base64")) { element2 = item.Value; if (element2.ValueKind != JsonValueKind.Null) { CloudEvent cloudEvent4 = cloudEvent; element2 = item.Value; cloudEvent4.Data = BinaryData.FromBytes(element2.GetBytesFromBase64()); cloudEvent.DataFormat = CloudEventDataFormat.Binary; } } else if (item.NameEquals("type")) { element2 = item.Value; if (element2.ValueKind != JsonValueKind.Null) { CloudEvent cloudEvent5 = cloudEvent; element2 = item.Value; cloudEvent5.Type = element2.GetString(); } } else if (item.NameEquals("time")) { element2 = item.Value; if (element2.ValueKind != JsonValueKind.Null) { CloudEvent cloudEvent6 = cloudEvent; element2 = item.Value; cloudEvent6.Time = element2.GetDateTimeOffset(); } } else if (item.NameEquals("specversion")) { CloudEvent cloudEvent7 = cloudEvent; element2 = item.Value; cloudEvent7.SpecVersion = element2.GetString(); } else if (item.NameEquals("dataschema")) { CloudEvent cloudEvent8 = cloudEvent; element2 = item.Value; cloudEvent8.DataSchema = element2.GetString(); } else if (item.NameEquals("datacontenttype")) { CloudEvent cloudEvent9 = cloudEvent; element2 = item.Value; cloudEvent9.DataContentType = element2.GetString(); } else if (item.NameEquals("subject")) { CloudEvent cloudEvent10 = cloudEvent; element2 = item.Value; cloudEvent10.Subject = element2.GetString(); } else if (!skipValidation) { IDictionary<string, object> extensionAttributes = cloudEvent.ExtensionAttributes; string name = item.Name; element2 = item.Value; extensionAttributes.Add(name, GetObject(ref element2)); } else { CloudEventExtensionAttributes<string, object> obj = (CloudEventExtensionAttributes<string, object>)cloudEvent.ExtensionAttributes; string name2 = item.Name; element2 = item.Value; obj.AddWithoutValidation(name2, GetObject(ref element2)); } } if (!skipValidation) { if (cloudEvent.Source == null) throw new ArgumentException("The source property must be specified in each CloudEvent. " + Environment.NewLine + "The `skipValidation` parameter can be set to 'true' in the CloudEvent.Parse or CloudEvent.ParseEvents method to skip this validation."); if (cloudEvent.Type == null) throw new ArgumentException("The type property must be specified in each CloudEvent. " + Environment.NewLine + "The `skipValidation` parameter can be set to 'true' in the CloudEvent.Parse or CloudEvent.ParseEvents method to skip this validation."); if (cloudEvent.Id == null) throw new ArgumentException("The Id property must be specified in each CloudEvent. " + Environment.NewLine + "The `skipValidation` parameter can be set to 'true' in the CloudEvent.Parse or CloudEvent.ParseEvents method to skip this validation."); if (cloudEvent.SpecVersion != "1.0") { if (cloudEvent.SpecVersion == null) throw new ArgumentException("The specverion was not set in at least one of the events in the payload. This type only supports specversion '1.0', which must be set for each event. " + Environment.NewLine + "The `skipValidation` parameter can be set to 'true' in the CloudEvent.Parse or CloudEvent.ParseEvents method to skip this validation." + Environment.NewLine + element.ToString(), "element"); throw new ArgumentException("The specverion value of '" + cloudEvent.SpecVersion + "' is not supported by CloudEvent. This type only supports specversion '1.0'. " + Environment.NewLine + "The `skipValidation` parameter can be set to 'true' in the CloudEvent.Parse or CloudEvent.ParseEvents method to skip this validation." + Environment.NewLine + element.ToString(), "element"); } } return cloudEvent; } public override void Write(Utf8JsonWriter writer, CloudEvent value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WritePropertyName("id"); writer.WriteStringValue(value.Id); writer.WritePropertyName("source"); writer.WriteStringValue(value.Source); writer.WritePropertyName("type"); writer.WriteStringValue(value.Type); if ((object)value.Data != null) { switch (value.DataFormat) { case CloudEventDataFormat.Binary: writer.WritePropertyName("data_base64"); writer.WriteBase64StringValue(value.Data.ToArray()); break; case CloudEventDataFormat.Json: using (JsonDocument jsonDocument = JsonDocument.Parse(value.Data.ToMemory(), default(JsonDocumentOptions))) { writer.WritePropertyName("data"); jsonDocument.RootElement.WriteTo(writer); } break; } } if (value.Time.HasValue) { writer.WritePropertyName("time"); writer.WriteStringValue(value.Time.Value); } writer.WritePropertyName("specversion"); writer.WriteStringValue(value.SpecVersion); if (value.DataSchema != null) { writer.WritePropertyName("dataschema"); writer.WriteStringValue(value.DataSchema); } if (value.DataContentType != null) { writer.WritePropertyName("datacontenttype"); writer.WriteStringValue(value.DataContentType); } if (value.Subject != null) { writer.WritePropertyName("subject"); writer.WriteStringValue(value.Subject); } foreach (KeyValuePair<string, object> extensionAttribute in value.ExtensionAttributes) { writer.WritePropertyName(extensionAttribute.Key); WriteObjectValue(writer, extensionAttribute.Value); } writer.WriteEndObject(); } private static void WriteObjectValue(Utf8JsonWriter writer, [System.Runtime.CompilerServices.Nullable(2)] object value) { if (value != null) { byte[] array = value as byte[]; if (array == null) { if (!(value is ReadOnlyMemory<byte>)) { if (value is int) { int value2 = (int)value; writer.WriteNumberValue(value2); } else { string text = value as string; if (text == null) { if (value is bool) { bool value3 = (bool)value; writer.WriteBooleanValue(value3); } else if (value is Guid) { Guid value4 = (Guid)value; writer.WriteStringValue(value4); } else { Uri uri = value as Uri; if ((object)uri == null) { if (value is DateTimeOffset) { DateTimeOffset value5 = (DateTimeOffset)value; writer.WriteStringValue(value5); } else if (value is DateTime) { DateTime value6 = (DateTime)value; writer.WriteStringValue(value6); } else { IEnumerable<KeyValuePair<string, object>> enumerable = value as IEnumerable<KeyValuePair<string, object>>; if (enumerable == null) { IEnumerable<object> enumerable2 = value as IEnumerable<object>; if (enumerable2 == null) throw new NotSupportedException("Not supported type " + value.GetType()?.ToString()); writer.WriteStartArray(); foreach (object item in enumerable2) { WriteObjectValue(writer, item); } writer.WriteEndArray(); } else { writer.WriteStartObject(); foreach (KeyValuePair<string, object> item2 in enumerable) { writer.WritePropertyName(item2.Key); WriteObjectValue(writer, item2.Value); } writer.WriteEndObject(); } } } else writer.WriteStringValue(uri.ToString()); } } else writer.WriteStringValue(text); } } else writer.WriteStringValue(Convert.ToBase64String(((ReadOnlyMemory<byte>)value).ToArray())); } else writer.WriteStringValue(Convert.ToBase64String(array)); } else writer.WriteNullValue(); } [System.Runtime.CompilerServices.NullableContext(2)] private static object GetObject([In] [System.Runtime.CompilerServices.IsReadOnly] ref JsonElement element) { switch (element.ValueKind) { case JsonValueKind.String: return element.GetString(); case JsonValueKind.Number: if (element.TryGetInt32(out int value)) return value; if (element.TryGetInt64(out long value2)) return value2; return element.GetDouble(); case JsonValueKind.True: return true; case JsonValueKind.False: return false; case JsonValueKind.Undefined: case JsonValueKind.Null: return null; case JsonValueKind.Object: { Dictionary<string, object> dictionary = new Dictionary<string, object>(); { foreach (JsonProperty item in element.EnumerateObject()) { Dictionary<string, object> dictionary2 = dictionary; string name = item.Name; JsonElement element3 = item.Value; dictionary2.Add(name, GetObject(ref element3)); } return dictionary; } } case JsonValueKind.Array: { List<object> list = new List<object>(); foreach (JsonElement item2 in element.EnumerateArray()) { JsonElement element2 = item2; list.Add(GetObject(ref element2)); } return list.ToArray(); } default: throw new NotSupportedException("Not supported value kind " + element.ValueKind.ToString()); } } } }