diff --git a/src/Elastic.Transport/Components/Serialization/IJsonSerializerOptionsProvider.cs b/src/Elastic.Transport/Components/Serialization/IJsonSerializerOptionsProvider.cs
new file mode 100644
index 0000000..10ec20e
--- /dev/null
+++ b/src/Elastic.Transport/Components/Serialization/IJsonSerializerOptionsProvider.cs
@@ -0,0 +1,61 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Elastic.Transport;
+
+///
+/// Provides an instance of to
+///
+public interface IJsonSerializerOptionsProvider
+{
+ ///
+ JsonSerializerOptions CreateJsonSerializerOptions();
+}
+
+///
+/// Default implementation of specialized in providing more converters and
+/// altering the shared used by and its derived classes
+///
+public class TransportSerializerOptionsProvider : IJsonSerializerOptionsProvider
+{
+ private readonly IReadOnlyCollection? _bakedInConverters;
+ private readonly IReadOnlyCollection? _userProvidedConverters;
+ private readonly Action? _mutateOptions;
+
+ ///
+ public JsonSerializerOptions? CreateJsonSerializerOptions()
+ {
+ var options = new JsonSerializerOptions();
+
+ foreach (var converter in _bakedInConverters ?? [])
+ options.Converters.Add(converter);
+
+ foreach (var converter in _userProvidedConverters ?? [])
+ options.Converters.Add(converter);
+
+ _mutateOptions?.Invoke(options);
+
+ return options;
+ }
+
+ ///
+ public TransportSerializerOptionsProvider() { }
+
+ ///
+ public TransportSerializerOptionsProvider(
+ IReadOnlyCollection bakedInConverters,
+ IReadOnlyCollection? userProvidedConverters,
+ Action? mutateOptions = null
+ )
+ {
+ _bakedInConverters = bakedInConverters;
+ _userProvidedConverters = userProvidedConverters;
+ _mutateOptions = mutateOptions;
+ }
+}
diff --git a/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs b/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs
index 36602fc..183d4cf 100644
--- a/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs
+++ b/src/Elastic.Transport/Components/Serialization/LowLevelRequestResponseSerializer.cs
@@ -2,43 +2,23 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
-using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
-using System.Threading;
-using System.Threading.Tasks;
-using Elastic.Transport.Extensions;
-using static Elastic.Transport.SerializationFormatting;
namespace Elastic.Transport;
///
-/// Default implementation for . This uses from System.Text.Json
.
+/// Default low level request/response-serializer implementation for which serializes using
+/// the Microsoft System.Text.Json library
///
-internal sealed class LowLevelRequestResponseSerializer : Serializer
+internal sealed class LowLevelRequestResponseSerializer : SystemTextJsonSerializer
{
///
/// Provides a static reusable reference to an instance of to promote reuse.
///
internal static readonly LowLevelRequestResponseSerializer Instance = new();
- private readonly Lazy _indented;
- private readonly Lazy _none;
-
- private IReadOnlyCollection AdditionalConverters { get; }
-
- private IList BakedInConverters { get; } = new List
- {
- new ExceptionConverter(),
- new ErrorCauseConverter(),
- new ErrorConverter(),
- new DynamicDictionaryConverter()
- };
-
/// >
public LowLevelRequestResponseSerializer() : this(null) { }
@@ -46,94 +26,12 @@ public LowLevelRequestResponseSerializer() : this(null) { }
/// >
///
/// Add more default converters onto being used
- public LowLevelRequestResponseSerializer(IEnumerable? converters)
- {
- AdditionalConverters = converters != null
- ? new ReadOnlyCollection(converters.ToList())
- : EmptyReadOnly.Collection;
- _indented = new Lazy(() => CreateSerializerOptions(Indented));
- _none = new Lazy(() => CreateSerializerOptions(None));
- }
-
- ///
- /// Creates used for serialization.
- /// Override on a derived serializer to change serialization.
- ///
- public JsonSerializerOptions CreateSerializerOptions(SerializationFormatting formatting)
- {
- var options = new JsonSerializerOptions
- {
- DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
- WriteIndented = formatting == Indented,
- };
- foreach (var converter in BakedInConverters)
- options.Converters.Add(converter);
- foreach (var converter in AdditionalConverters)
- options.Converters.Add(converter);
-
- return options;
-
- }
-
- private static bool TryReturnDefault(Stream? stream, out T deserialize)
- {
- deserialize = default;
- return stream == null || stream == Stream.Null || (stream.CanSeek && stream.Length == 0);
- }
-
- private JsonSerializerOptions GetFormatting(SerializationFormatting formatting) => formatting == None ? _none.Value : _indented.Value;
-
- /// >
- public override object Deserialize(Type type, Stream stream)
- {
- if (TryReturnDefault(stream, out object deserialize)) return deserialize;
-
- return JsonSerializer.Deserialize(stream, type, _none.Value)!;
- }
-
- /// >
- public override T Deserialize(Stream stream)
- {
- if (TryReturnDefault(stream, out T deserialize)) return deserialize;
-
- return JsonSerializer.Deserialize(stream, _none.Value);
- }
-
- /// >
- public override void Serialize(T data, Stream stream, SerializationFormatting formatting = None)
- {
- using var writer = new Utf8JsonWriter(stream);
- if (data == null)
- JsonSerializer.Serialize(writer, null, typeof(object), GetFormatting(formatting));
- //TODO validate if we can avoid boxing by checking if data is typeof(object)
- else
- JsonSerializer.Serialize(writer, data, data.GetType(), GetFormatting(formatting));
- }
-
- /// >
- public override async Task SerializeAsync(T data, Stream stream, SerializationFormatting formatting = None,
- CancellationToken cancellationToken = default
- )
- {
- if (data == null)
- await JsonSerializer.SerializeAsync(stream, null, typeof(object), GetFormatting(formatting), cancellationToken).ConfigureAwait(false);
- else
- await JsonSerializer.SerializeAsync(stream, data, data.GetType(), GetFormatting(formatting), cancellationToken).ConfigureAwait(false);
- }
-
- /// >
- public override ValueTask