diff --git a/examples/WireMock.Net.Console.NET8/Program.cs b/examples/WireMock.Net.Console.NET8/Program.cs
index 9ca8b200..36929f77 100644
--- a/examples/WireMock.Net.Console.NET8/Program.cs
+++ b/examples/WireMock.Net.Console.NET8/Program.cs
@@ -1,8 +1,6 @@
// Copyright © WireMock.Net
-using System.IO;
using System.Reflection;
-using System.Threading.Tasks;
using log4net;
using log4net.Config;
using log4net.Repository;
@@ -12,7 +10,7 @@ namespace WireMock.Net.Console.NET8;
static class Program
{
- private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
+ private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()!);
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
static async Task Main(params string[] args)
diff --git a/examples/WireMock.Net.WebApplication.IIS/WireMockService.cs b/examples/WireMock.Net.WebApplication.IIS/WireMockService.cs
index 249ddb9b..6c3cf279 100644
--- a/examples/WireMock.Net.WebApplication.IIS/WireMockService.cs
+++ b/examples/WireMock.Net.WebApplication.IIS/WireMockService.cs
@@ -70,7 +70,7 @@ public class WireMockService : IWireMockService
_server = WireMockServer.Start(_settings);
- _logger.LogInformation($"WireMock.Net server settings {JsonConvert.SerializeObject(_settings)}");
+ _logger.LogInformation("WireMock.Net server settings {Settings}", JsonConvert.SerializeObject(_settings));
}
public void Stop()
diff --git a/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs b/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs
index e11f630c..4e2df9e3 100644
--- a/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs
+++ b/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs
@@ -357,6 +357,7 @@ public class WireMockServerSettings
/// Default is .
///
[PublicAPI]
+ [JsonConverter(typeof(WireMockSettingsJsonConverter))]
public IJsonConverter DefaultJsonSerializer { get; set; }
///
@@ -367,7 +368,7 @@ public class WireMockServerSettings
/// Default is .
///
[PublicAPI]
- [JsonIgnore]
+ [JsonConverter(typeof(WireMockSettingsJsonConverter))]
public IJsonBodyTransformer DefaultJsonBodyTransformer { get; set; }
///
diff --git a/src/WireMock.Net.Shared/Settings/WireMockSettingsJsonConverter.cs b/src/WireMock.Net.Shared/Settings/WireMockSettingsJsonConverter.cs
new file mode 100644
index 00000000..8d0554aa
--- /dev/null
+++ b/src/WireMock.Net.Shared/Settings/WireMockSettingsJsonConverter.cs
@@ -0,0 +1,151 @@
+// Copyright © WireMock.Net
+
+using System.Reflection;
+using JsonConverter.Abstractions;
+using JsonConverter.Newtonsoft.Json;
+using JsonConverter.System.Text.Json;
+using Newtonsoft.Json;
+using WireMock.Transformers;
+using NewtonsoftJsonConverterBase = Newtonsoft.Json.JsonConverter;
+
+namespace WireMock.Settings;
+
+///
+/// WireMockSettingsJsonConverter serializes and deserializes the special interface-based settings properties as type names.
+///
+public class WireMockSettingsJsonConverter : NewtonsoftJsonConverterBase
+{
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return typeof(IJsonConverter).IsAssignableFrom(objectType) || typeof(IJsonBodyTransformer).IsAssignableFrom(objectType);
+ }
+
+ ///
+ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
+ {
+ writer.WriteValue(value?.GetType().FullName);
+ }
+
+ ///
+ public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return existingValue ?? CreateDefaultValue(objectType);
+ }
+
+ if (reader.TokenType != JsonToken.String)
+ {
+ reader.Skip();
+ return existingValue ?? CreateDefaultValue(objectType);
+ }
+
+ var typeName = reader.Value as string;
+
+ if (typeof(IJsonConverter).IsAssignableFrom(objectType))
+ {
+ return CreateJsonConverter(typeName) ?? existingValue ?? new NewtonsoftJsonConverter();
+ }
+
+ if (typeof(IJsonBodyTransformer).IsAssignableFrom(objectType))
+ {
+ var settings = ExtractSettings(existingValue as IJsonBodyTransformer);
+ return settings != null
+ ? CreateJsonBodyTransformer(typeName, settings) ?? existingValue ?? new NewtonsoftJsonBodyTransformer(settings)
+ : existingValue;
+ }
+
+ return existingValue;
+ }
+
+ private static object? CreateDefaultValue(Type objectType)
+ {
+ if (typeof(IJsonConverter).IsAssignableFrom(objectType))
+ {
+ return new NewtonsoftJsonConverter();
+ }
+
+ return null;
+ }
+
+ private static IJsonConverter? CreateJsonConverter(string? typeName)
+ {
+ if (string.IsNullOrWhiteSpace(typeName))
+ {
+ return null;
+ }
+
+ if (typeName == nameof(NewtonsoftJsonConverter) || typeName == typeof(NewtonsoftJsonConverter).FullName)
+ {
+ return new NewtonsoftJsonConverter();
+ }
+
+ if (typeName == nameof(SystemTextJsonConverter) || typeName == typeof(SystemTextJsonConverter).FullName)
+ {
+ return new SystemTextJsonConverter();
+ }
+
+ var type = GetType(typeName);
+ if (type == null || !typeof(IJsonConverter).IsAssignableFrom(type))
+ {
+ return null;
+ }
+
+ return Activator.CreateInstance(type) as IJsonConverter;
+ }
+
+ private static IJsonBodyTransformer? CreateJsonBodyTransformer(string? typeName, WireMockServerSettings settings)
+ {
+ if (string.IsNullOrWhiteSpace(typeName))
+ {
+ return null;
+ }
+
+ if (typeName == nameof(NewtonsoftJsonBodyTransformer) || typeName == typeof(NewtonsoftJsonBodyTransformer).FullName)
+ {
+ return new NewtonsoftJsonBodyTransformer(settings);
+ }
+
+ if (typeName == nameof(SystemTextJsonBodyTransformer) || typeName == typeof(SystemTextJsonBodyTransformer).FullName)
+ {
+ return new SystemTextJsonBodyTransformer(settings);
+ }
+
+ var type = GetType(typeName);
+ if (type == null || !typeof(IJsonBodyTransformer).IsAssignableFrom(type))
+ {
+ return null;
+ }
+
+ var constructorWithSettings = type.GetConstructor([typeof(WireMockServerSettings)]);
+ if (constructorWithSettings != null)
+ {
+ return constructorWithSettings.Invoke([settings]) as IJsonBodyTransformer;
+ }
+
+ return Activator.CreateInstance(type) as IJsonBodyTransformer;
+ }
+
+ private static WireMockServerSettings? ExtractSettings(IJsonBodyTransformer? existingValue)
+ {
+ if (existingValue == null)
+ {
+ return null;
+ }
+
+ return existingValue.GetType()
+ .GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
+ .Where(field => typeof(WireMockServerSettings).IsAssignableFrom(field.FieldType))
+ .Select(field => field.GetValue(existingValue) as WireMockServerSettings)
+ .FirstOrDefault(settings => settings != null);
+ }
+
+ private static Type? GetType(string typeName)
+ {
+ return Type.GetType(typeName, throwOnError: false) ??
+ AppDomain.CurrentDomain.GetAssemblies()
+ .Select(assembly => assembly.GetType(typeName, throwOnError: false))
+ .FirstOrDefault(foundType => foundType != null);
+ }
+}
\ No newline at end of file
diff --git a/src/dotnet-WireMock.Net/Program.cs b/src/dotnet-WireMock.Net/Program.cs
index 69cb172a..60fac428 100644
--- a/src/dotnet-WireMock.Net/Program.cs
+++ b/src/dotnet-WireMock.Net/Program.cs
@@ -1,7 +1,5 @@
// Copyright © WireMock.Net
-using System;
-using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using WireMock.Logging;
using WireMock.Net.StandAlone;
diff --git a/test/WireMock.Net.Tests/Settings/WireMockServerSettingsJsonTests.cs b/test/WireMock.Net.Tests/Settings/WireMockServerSettingsJsonTests.cs
new file mode 100644
index 00000000..691142fe
--- /dev/null
+++ b/test/WireMock.Net.Tests/Settings/WireMockServerSettingsJsonTests.cs
@@ -0,0 +1,82 @@
+// Copyright © WireMock.Net
+
+using JsonConverter.Newtonsoft.Json;
+using JsonConverter.System.Text.Json;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using WireMock.Settings;
+using WireMock.Transformers;
+
+namespace WireMock.Net.Tests.Settings;
+
+public class WireMockServerSettingsJsonTests
+{
+ [Fact]
+ public void NewtonsoftJson_Serialize_WireMockServerSettings_HandlesSpecialProperties_AndKeepsOtherPropertiesAsIs()
+ {
+ // Arrange
+ var settings = new WireMockServerSettings
+ {
+ Port = 1234,
+ AdminPath = "/custom-admin",
+ StartAdminInterface = true,
+ DefaultJsonSerializer = new SystemTextJsonConverter()
+ };
+ settings.DefaultJsonBodyTransformer = new SystemTextJsonBodyTransformer(settings);
+
+ // Act
+ var json = JsonConvert.SerializeObject(settings);
+ var jsonObject = JObject.Parse(json);
+
+ // Assert
+ jsonObject[nameof(WireMockServerSettings.Port)]!.Value().Should().Be(1234);
+ jsonObject[nameof(WireMockServerSettings.AdminPath)]!.Value().Should().Be("/custom-admin");
+ jsonObject[nameof(WireMockServerSettings.StartAdminInterface)]!.Value().Should().BeTrue();
+ jsonObject[nameof(WireMockServerSettings.DefaultJsonSerializer)]!.Type.Should().Be(JTokenType.String);
+ jsonObject[nameof(WireMockServerSettings.DefaultJsonSerializer)]!.Value().Should().Be(typeof(SystemTextJsonConverter).FullName);
+ jsonObject[nameof(WireMockServerSettings.DefaultJsonBodyTransformer)]!.Type.Should().Be(JTokenType.String);
+ jsonObject[nameof(WireMockServerSettings.DefaultJsonBodyTransformer)]!.Value().Should().Be(typeof(SystemTextJsonBodyTransformer).FullName);
+ }
+
+ [Fact]
+ public void NewtonsoftJson_Deserialize_WireMockServerSettings_HandlesSpecialProperties_AndKeepsOtherPropertiesAsIs()
+ {
+ // Arrange
+ var json =
+ $"{{\"{nameof(WireMockServerSettings.Port)}\":4321," +
+ $"\"{nameof(WireMockServerSettings.AdminPath)}\":\"/custom-admin\"," +
+ $"\"{nameof(WireMockServerSettings.StartAdminInterface)}\":true," +
+ $"\"{nameof(WireMockServerSettings.DefaultJsonSerializer)}\":\"{typeof(SystemTextJsonConverter).FullName}\"," +
+ $"\"{nameof(WireMockServerSettings.DefaultJsonBodyTransformer)}\":\"{typeof(SystemTextJsonBodyTransformer).FullName}\"}}";
+
+ // Act
+ var settings = JsonConvert.DeserializeObject(json);
+
+ // Assert
+ settings.Should().NotBeNull();
+ settings!.Port.Should().Be(4321);
+ settings.AdminPath.Should().Be("/custom-admin");
+ settings.StartAdminInterface.Should().BeTrue();
+ settings.DefaultJsonSerializer.Should().BeOfType();
+ settings.DefaultJsonBodyTransformer.Should().BeOfType();
+ }
+
+ [Fact]
+ public void NewtonsoftJson_Deserialize_WireMockServerSettings_LegacyObjects_AreIgnored_AndOtherPropertiesStayUntouched()
+ {
+ // Arrange
+ var json =
+ $"{{\"{nameof(WireMockServerSettings.Port)}\":9876," +
+ $"\"{nameof(WireMockServerSettings.DefaultJsonSerializer)}\":{{}}," +
+ $"\"{nameof(WireMockServerSettings.DefaultJsonBodyTransformer)}\":{{}}}}";
+
+ // Act
+ var settings = JsonConvert.DeserializeObject(json);
+
+ // Assert
+ settings.Should().NotBeNull();
+ settings!.Port.Should().Be(9876);
+ settings.DefaultJsonSerializer.Should().BeOfType();
+ settings.DefaultJsonBodyTransformer.Should().BeOfType();
+ }
+}
\ No newline at end of file