Optimize encoding

This commit is contained in:
Ben Young 2024-03-20 11:15:20 +00:00 committed by GitHub
parent 6385133391
commit f43c80334f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 9 deletions

View File

@ -80,6 +80,8 @@ namespace CloudNative.CloudEvents.NewtonsoftJson
/// </remarks> /// </remarks>
public class JsonEventFormatter : CloudEventFormatter public class JsonEventFormatter : CloudEventFormatter
{ {
private static readonly Encoding noBomUtf8 = new UTF8Encoding(false);
private static readonly IReadOnlyDictionary<CloudEventAttributeType, JTokenType> expectedTokenTypesForReservedAttributes = private static readonly IReadOnlyDictionary<CloudEventAttributeType, JTokenType> expectedTokenTypesForReservedAttributes =
new Dictionary<CloudEventAttributeType, JTokenType> new Dictionary<CloudEventAttributeType, JTokenType>
{ {
@ -395,7 +397,7 @@ namespace CloudNative.CloudEvents.NewtonsoftJson
CharSet = Encoding.UTF8.WebName CharSet = Encoding.UTF8.WebName
}; };
var stream = new MemoryStream(); var stream = this.GetMemoryStream();
var writer = CreateJsonTextWriter(stream); var writer = CreateJsonTextWriter(stream);
WriteCloudEventForBatchOrStructuredMode(writer, cloudEvent); WriteCloudEventForBatchOrStructuredMode(writer, cloudEvent);
writer.Flush(); writer.Flush();
@ -425,7 +427,7 @@ namespace CloudNative.CloudEvents.NewtonsoftJson
CharSet = Encoding.UTF8.WebName CharSet = Encoding.UTF8.WebName
}; };
var stream = new MemoryStream(); var stream = this.GetMemoryStream();
var writer = CreateJsonTextWriter(stream); var writer = CreateJsonTextWriter(stream);
writer.WriteStartArray(); writer.WriteStartArray();
foreach (var cloudEvent in cloudEvents) foreach (var cloudEvent in cloudEvents)
@ -568,13 +570,21 @@ namespace CloudNative.CloudEvents.NewtonsoftJson
ContentType contentType = new ContentType(cloudEvent.DataContentType ?? JsonMediaType); ContentType contentType = new ContentType(cloudEvent.DataContentType ?? JsonMediaType);
if (IsJsonMediaType(contentType.MediaType)) if (IsJsonMediaType(contentType.MediaType))
{ {
// TODO: Make this more efficient. We could write to a StreamWriter with a MemoryStream, var encoding = MimeUtilities.GetEncoding(contentType);
// but then we end up with a BOM in most cases, which I suspect we don't want. if (ReferenceEquals(encoding, Encoding.UTF8))
// An alternative is to make sure that contentType.GetEncoding() always returns an encoding {
// without a preamble (or rewrite StreamWriter...) using var stream = this.GetMemoryStream();
using var writer = new StreamWriter(stream, noBomUtf8);
Serializer.Serialize(writer, cloudEvent.Data);
writer.Flush();
return stream.ToArray();
}
else
{
var stringWriter = new StringWriter(); var stringWriter = new StringWriter();
Serializer.Serialize(stringWriter, cloudEvent.Data); Serializer.Serialize(stringWriter, cloudEvent.Data);
return MimeUtilities.GetEncoding(contentType).GetBytes(stringWriter.ToString()); return encoding.GetBytes(stringWriter.ToString());
}
} }
if (contentType.MediaType.StartsWith("text/") && cloudEvent.Data is string text) if (contentType.MediaType.StartsWith("text/") && cloudEvent.Data is string text)
{ {
@ -614,6 +624,13 @@ namespace CloudNative.CloudEvents.NewtonsoftJson
} }
} }
/// <summary>
/// Creates a stream that can be written to to provide buffered array data.
/// </summary>
/// <returns>A memory stream.</returns>
protected virtual MemoryStream GetMemoryStream()
=> new MemoryStream();
/// <summary> /// <summary>
/// Creates a <see cref="JsonReader"/> for the given stream. This may be overridden in derived classes to /// Creates a <see cref="JsonReader"/> for the given stream. This may be overridden in derived classes to
/// customize the JSON parsing process, subject to the constraints listed in the remarks. /// customize the JSON parsing process, subject to the constraints listed in the remarks.