This commit is contained in:
Stef Heyenrath
2025-12-20 10:32:26 +01:00
parent e6e4138466
commit 708af55051
14 changed files with 83 additions and 43 deletions

View File

@@ -32,7 +32,7 @@ public class ResponseModel
public object? BodyAsJson { get; set; } public object? BodyAsJson { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. /// Gets or sets a value indicating whether the Json Body String needs to be indented.
/// </summary> /// </summary>
public bool? BodyAsJsonIndented { get; set; } public bool? BodyAsJsonIndented { get; set; }

View File

@@ -37,7 +37,7 @@ public interface IBodyData
object? BodyAsJson { get; set; } object? BodyAsJson { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. /// Gets or sets a value indicating whether the Json Body String needs to be indented.
/// </summary> /// </summary>
bool? BodyAsJsonIndented { get; set; } bool? BodyAsJsonIndented { get; set; }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>WireMock.Net.Routing extends WireMock.Net with modern, minimal-API-style routing for .NET</Description> <Description>WireMock.Net.Routing extends WireMock.Net with modern, minimal-API-style routing for .NET</Description>
<Authors>Gennadii Saltyshchak</Authors> <Authors>Gennadii Saltyshchak</Authors>
@@ -25,7 +25,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.7.0" /> <PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Newtonsoft.Json;
using Stef.Validation; using Stef.Validation;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
@@ -164,8 +163,8 @@ public class MappingBuilder : IMappingBuilder
} }
} }
private static string ToJson(object value) private string ToJson(object value)
{ {
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault); return _settings.DefaultJsonSerializer.Serialize(value, JsonSerializationConstants.JsonConverterOptionsDefault);
} }
} }

View File

@@ -2,7 +2,8 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using JsonConverter.Abstractions;
using JsonConverter.Newtonsoft.Json;
using Stef.Validation; using Stef.Validation;
using WireMock.Settings; using WireMock.Settings;
@@ -12,12 +13,15 @@ internal class MappingToFileSaver
{ {
private readonly WireMockServerSettings _settings; private readonly WireMockServerSettings _settings;
private readonly MappingConverter _mappingConverter; private readonly MappingConverter _mappingConverter;
private readonly IJsonConverter _jsonConverter;
private readonly MappingFileNameSanitizer _fileNameSanitizer; private readonly MappingFileNameSanitizer _fileNameSanitizer;
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter) public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
{ {
_settings = Guard.NotNull(settings); _settings = Guard.NotNull(settings);
_mappingConverter = Guard.NotNull(mappingConverter); _mappingConverter = Guard.NotNull(mappingConverter);
_jsonConverter = settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter();
_fileNameSanitizer = new MappingFileNameSanitizer(settings); _fileNameSanitizer = new MappingFileNameSanitizer(settings);
} }
@@ -56,6 +60,8 @@ internal class MappingToFileSaver
{ {
_settings.Logger.Info("Saving Mapping file {0}", path); _settings.Logger.Info("Saving Mapping file {0}", path);
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault)); var json = _jsonConverter.Serialize(value, JsonSerializationConstants.JsonConverterOptionsDefault);
_settings.FileSystemHandler.WriteMappingFile(path, json);
} }
} }

View File

@@ -7,7 +7,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using JsonConverter.Abstractions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Stef.Validation; using Stef.Validation;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
@@ -826,25 +826,31 @@ public partial class WireMockServer
} }
} }
private static Encoding? ToEncoding(EncodingModel? encodingModel) private ResponseMessage ToJson<T>(T result, bool keepNullValues = false, object? statusCode = null)
{ {
return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null; var jsonOptions = new JsonConverterOptions
} {
WriteIndented = true,
IgnoreNullValues = !keepNullValues
};
private static ResponseMessage ToJson<T>(T result, bool keepNullValues = false, object? statusCode = null)
{
return new ResponseMessage return new ResponseMessage
{ {
BodyData = new BodyData BodyData = new BodyData
{ {
DetectedBodyType = BodyType.String, DetectedBodyType = BodyType.String,
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues : JsonSerializationConstants.JsonSerializerSettingsDefault) BodyAsString = _settings.DefaultJsonSerializer.Serialize(result!, jsonOptions)
}, },
StatusCode = statusCode ?? (int)HttpStatusCode.OK, StatusCode = statusCode ?? (int)HttpStatusCode.OK,
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(WireMockConstants.ContentTypeJson) } } Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(WireMockConstants.ContentTypeJson) } }
}; };
} }
private static Encoding? ToEncoding(EncodingModel? encodingModel)
{
return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
}
private static ResponseMessage ToResponseMessage(string text) private static ResponseMessage ToResponseMessage(string text)
{ {
return new ResponseMessage return new ResponseMessage

View File

@@ -8,7 +8,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Runtime;
using System.Threading; using System.Threading;
using AnyOfTypes; using AnyOfTypes;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -360,7 +359,7 @@ public partial class WireMockServer : IWireMockServer
{ {
_settings = Guard.NotNull(settings); _settings = Guard.NotNull(settings);
_mappingSerializer = new MappingSerializer(settings.MappingJsonSerializer ?? new NewtonsoftJsonConverter()); _mappingSerializer = new MappingSerializer(settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter());
// Set default values if not provided // Set default values if not provided
_settings.Logger = settings.Logger ?? new WireMockNullLogger(); _settings.Logger = settings.Logger ?? new WireMockNullLogger();

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Minimal version from the lightweight Http Mocking Server for .NET</Description> <Description>Minimal version from the lightweight Http Mocking Server for .NET</Description>
<AssemblyTitle>WireMock.Net.Minimal</AssemblyTitle> <AssemblyTitle>WireMock.Net.Minimal</AssemblyTitle>
@@ -57,8 +57,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!--<PackageReference Include="JsonConverter.Abstractions" Version="0.7.0" />--> <!--<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />-->
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.7.0" /> <!--<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />-->
<PackageReference Include="NJsonSchema.Extensions" Version="0.1.0" /> <PackageReference Include="NJsonSchema.Extensions" Version="0.1.0" />
<PackageReference Include="NSwag.Core" Version="13.16.1" /> <PackageReference Include="NSwag.Core" Version="13.16.1" />
<PackageReference Include="SimMetrics.Net" Version="1.0.5" /> <PackageReference Include="SimMetrics.Net" Version="1.0.5" />
@@ -118,13 +118,13 @@
<!-- https://github.com/wiremock/WireMock.Net/issues/507 --> <!-- https://github.com/wiremock/WireMock.Net/issues/507 -->
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" /> <PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.7.0" /> <PackageReference Include="JsonConverter.System.Text.Json" Version="0.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'"> <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Scriban.Signed" Version="5.5.0" /> <PackageReference Include="Scriban.Signed" Version="5.5.0" />
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.7.0" /> <PackageReference Include="JsonConverter.System.Text.Json" Version="0.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">

View File

@@ -33,7 +33,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.7.0" /> <PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
<PackageReference Include="RestEase" Version="1.6.4" /> <PackageReference Include="RestEase" Version="1.6.4" />
<PackageReference Include="Stef.Validation" Version="0.1.1" /> <PackageReference Include="Stef.Validation" Version="0.1.1" />
</ItemGroup> </ItemGroup>

View File

@@ -1,5 +1,6 @@
// Copyright © WireMock.Net // Copyright © WireMock.Net
using JsonConverter.Abstractions;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
@@ -7,24 +8,30 @@ namespace WireMock.Serialization;
internal static class JsonSerializationConstants internal static class JsonSerializationConstants
{ {
public static readonly JsonSerializerSettings JsonSerializerSettingsDefault = new() internal static readonly JsonConverterOptions JsonConverterOptionsDefault = new()
{ {
Formatting = Formatting.Indented, WriteIndented = true,
NullValueHandling = NullValueHandling.Ignore IgnoreNullValues = true
}; };
public static readonly JsonSerializerSettings JsonSerializerSettingsIncludeNullValues = new() //internal static readonly JsonSerializerSettings JsonSerializerSettingsDefault = new()
//{
// Formatting = Formatting.Indented,
// NullValueHandling = NullValueHandling.Ignore
//};
internal static readonly JsonSerializerSettings JsonSerializerSettingsIncludeNullValues = new()
{ {
Formatting = Formatting.Indented, Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Include NullValueHandling = NullValueHandling.Include
}; };
public static readonly JsonSerializerSettings JsonDeserializerSettingsWithDateParsingNone = new() internal static readonly JsonSerializerSettings JsonDeserializerSettingsWithDateParsingNone = new()
{ {
DateParseHandling = DateParseHandling.None DateParseHandling = DateParseHandling.None
}; };
public static readonly JsonSerializerSettings JsonSerializerSettingsPact = new() internal static readonly JsonSerializerSettings JsonSerializerSettingsPact = new()
{ {
Formatting = Formatting.Indented, Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore,

View File

@@ -15,6 +15,7 @@ using WireMock.Types;
using System.Globalization; using System.Globalization;
using WireMock.Models; using WireMock.Models;
using JsonConverter.Abstractions; using JsonConverter.Abstractions;
using JsonConverter.Newtonsoft.Json;
#if USE_ASPNETCORE #if USE_ASPNETCORE
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -341,12 +342,12 @@ public class WireMockServerSettings
public HandlebarsSettings? HandlebarsSettings { get; set; } public HandlebarsSettings? HandlebarsSettings { get; set; }
/// <summary> /// <summary>
/// Gets or sets the JSON converter used for MappingModel serialization. /// Gets or sets the default JSON converter used for serialization.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Set this property to customize how objects are serialized to and deserialized from JSON during mapping. /// Set this property to customize how objects are serialized to and deserialized from JSON during mapping.
/// If not set, the NewtonsoftJsonConverter will be used. /// Default is <see cref="NewtonsoftJsonConverter"/>.
/// </remarks> /// </remarks>
[PublicAPI] [PublicAPI]
public IJsonConverter? MappingJsonSerializer { get; set; } public IJsonConverter DefaultJsonSerializer { get; set; } = new NewtonsoftJsonConverter();
} }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Shared interfaces, models, enumerations and types.</Description> <Description>Shared interfaces, models, enumerations and types.</Description>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
@@ -48,9 +48,10 @@
</PackageReference> </PackageReference>
<PackageReference Include="Stef.Validation" Version="0.1.1" /> <PackageReference Include="Stef.Validation" Version="0.1.1" />
<PackageReference Include="AnyOf" Version="0.4.0" /> <PackageReference Include="AnyOf" Version="0.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <!--<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />-->
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.0" />
<PackageReference Include="JsonConverter.Abstractions" Version="0.7.0" /> <!--<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />-->
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,6 +4,7 @@ using System;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using JsonConverter.Newtonsoft.Json;
using Moq; using Moq;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NFluent; using NFluent;
@@ -316,12 +317,11 @@ public class ResponseWithBodyTests
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
Check.That(response.Message.StatusCode).IsEqualTo(200); Check.That(response.Message.StatusCode).IsEqualTo(200);
Check.That(response.Message.BodyData.BodyAsString).Contains("File deleted."); Check.That(response.Message.BodyData?.BodyAsString).Contains("File deleted.");
} }
#if !(NET451 || NET452)
[Fact] [Fact]
public async Task Response_ProvideResponse_WithBody_IJsonConverter_SystemTextJson() public async Task Response_ProvideResponse_WithBody_NewtonsoftJsonConverter()
{ {
// Arrange // Arrange
var requestBody = new BodyData var requestBody = new BodyData
@@ -331,13 +331,34 @@ public class ResponseWithBodyTests
}; };
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, requestBody); var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, requestBody);
var responseBuilder = Response.Create().WithBody(new { foo = "bar", n = 42 }, new JsonConverter.System.Text.Json.SystemTextJsonConverter()); var responseBuilder = Response.Create().WithBody(new { foo = "< > & ' 😀 👍 ❤️", n = 42 }, new NewtonsoftJsonConverter());
// Act // Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false); var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert // Assert
response.Message.BodyData!.BodyAsString.Should().Be(@"{""foo"":""bar"",""n"":42}"); response.Message.BodyData!.BodyAsString.Should().Be("""{"foo":"< > & ' 😀 👍 ","n":42}""");
}
#if !(NET451 || NET452 || NET461)
[Fact]
public async Task Response_ProvideResponse_WithBody_SystemTextJsonConverter()
{
// Arrange
var requestBody = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = "abc"
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, requestBody);
var responseBuilder = Response.Create().WithBody(new { foo = "< > & ' 😀 👍 ❤️", n = 42 }, new JsonConverter.System.Text.Json.SystemTextJsonConverter());
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData!.BodyAsString.Should().Be("""{"foo":"\u003C \u003E \u0026 \u0027 \uD83D\uDE00 \uD83D\uDC4D \u2764\uFE0F","n":42}""");
} }
#endif #endif
} }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
@@ -103,7 +103,7 @@
<ItemGroup Condition="'$(TargetFramework)' != 'net452'"> <ItemGroup Condition="'$(TargetFramework)' != 'net452'">
<PackageReference Include="System.Net.Http.Json" Version="8.0.1" /> <PackageReference Include="System.Net.Http.Json" Version="8.0.1" />
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.7.0" /> <!--<PackageReference Include="JsonConverter.System.Text.Json" Version="0.8.0" />-->
<PackageReference Include="Google.Protobuf" Version="3.25.1" /> <PackageReference Include="Google.Protobuf" Version="3.25.1" />
<PackageReference Include="Grpc.Net.Client" Version="2.60.0" /> <PackageReference Include="Grpc.Net.Client" Version="2.60.0" />
<PackageReference Include="Grpc.Tools" Version="2.60.0"> <PackageReference Include="Grpc.Tools" Version="2.60.0">