diff --git a/src/OrchardCore/OrchardCore.Infrastructure/Documents/DefaultDocumentSerializer.cs b/src/OrchardCore/OrchardCore.Infrastructure/Documents/DefaultDocumentSerializer.cs index c3ddb51be98..6a158569333 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure/Documents/DefaultDocumentSerializer.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure/Documents/DefaultDocumentSerializer.cs @@ -1,6 +1,7 @@ +using System; using System.IO; using System.IO.Compression; -using System.Text; +using System.Linq; using System.Text.Json; using System.Threading.Tasks; using OrchardCore.Data.Documents; @@ -12,15 +13,19 @@ namespace OrchardCore.Documents /// public class DefaultDocumentSerializer : IDocumentSerializer { - public static readonly DefaultDocumentSerializer Instance = new(); + private static readonly byte[] _gZipHeaderBytes = [0x1f, 0x8b]; + + private readonly JsonSerializerOptions _serializerOptions; - public DefaultDocumentSerializer() + public DefaultDocumentSerializer(JsonSerializerOptions serializerOptions) { + _serializerOptions = serializerOptions; } - public Task SerializeAsync(TDocument document, int compressThreshold = int.MaxValue) where TDocument : class, IDocument, new() + public Task SerializeAsync(TDocument document, int compressThreshold = int.MaxValue) + where TDocument : class, IDocument, new() { - var data = Encoding.UTF8.GetBytes(JConvert.SerializeObject(document)); + var data = JsonSerializer.SerializeToUtf8Bytes(document, _serializerOptions); if (data.Length >= compressThreshold) { data = Compress(data); @@ -29,22 +34,32 @@ public DefaultDocumentSerializer() return Task.FromResult(data); } - public Task DeserializeAsync(byte[] data) where TDocument : class, IDocument, new() + public Task DeserializeAsync(byte[] data) + where TDocument : class, IDocument, new() { if (IsCompressed(data)) { data = Decompress(data); } - var document = JConvert.DeserializeObject(Encoding.UTF8.GetString(data)); + using var ms = new MemoryStream(data); + + var document = JsonSerializer.Deserialize(ms, _serializerOptions); return Task.FromResult(document); } - private static readonly byte[] _gZipHeaderBytes = [0x1f, 0x8b]; + internal static bool IsCompressed(byte[] data) + { + // Ensure data is at least as long as the GZip header + if (data.Length >= _gZipHeaderBytes.Length) + { + // Compare the header bytes. + return data.Take(_gZipHeaderBytes.Length).SequenceEqual(_gZipHeaderBytes); + } - internal static bool IsCompressed(byte[] data) => - data.Length < _gZipHeaderBytes.Length && data[0..1] == _gZipHeaderBytes; + return false; + } internal static byte[] Compress(byte[] data) { diff --git a/src/OrchardCore/OrchardCore.Infrastructure/Documents/Options/DocumentOptionsSetup.cs b/src/OrchardCore/OrchardCore.Infrastructure/Documents/Options/DocumentOptionsSetup.cs index 99bfad145c3..f568a76975a 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure/Documents/Options/DocumentOptionsSetup.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure/Documents/Options/DocumentOptionsSetup.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using OrchardCore.Environment.Shell.Configuration; +using OrchardCore.Json; namespace OrchardCore.Documents.Options { @@ -11,13 +12,20 @@ public class DocumentOptionsSetup : IConfigureNamedOptions public static readonly TimeSpan DefaultFailoverRetryLatency = TimeSpan.FromSeconds(30); private readonly IShellConfiguration _shellConfiguration; + private readonly DocumentJsonSerializerOptions _documentJsonSerializerOptions; - public DocumentOptionsSetup(IShellConfiguration shellConfiguration) + private DefaultDocumentSerializer _defaultDocumentSerializer; + + public DocumentOptionsSetup( + IShellConfiguration shellConfiguration, + IOptions documentJsonSerializerOptions) { _shellConfiguration = shellConfiguration; + _documentJsonSerializerOptions = documentJsonSerializerOptions.Value; } - public void Configure(DocumentOptions options) => Configure(string.Empty, options); + public void Configure(DocumentOptions options) + => Configure(string.Empty, options); public void Configure(string name, DocumentOptions options) { @@ -46,7 +54,7 @@ public void Configure(string name, DocumentOptions options) ?? sharedConfig.SynchronizationLatency ?? TimeSpan.FromSeconds(1); - options.Serializer = DefaultDocumentSerializer.Instance; + options.Serializer = _defaultDocumentSerializer ??= new DefaultDocumentSerializer(_documentJsonSerializerOptions.SerializerOptions); options.CompressThreshold = namedConfig.CompressThreshold; if (options.CompressThreshold == 0)