This commit is contained in:
Stef Heyenrath
2026-02-14 08:59:23 +01:00
23 changed files with 533 additions and 110 deletions

View File

@@ -32,7 +32,7 @@ public class ResponseModel
public object? BodyAsJson { get; set; }
/// <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>
public bool? BodyAsJsonIndented { get; set; }

View File

@@ -37,7 +37,7 @@ public interface IBodyData
object? BodyAsJson { get; set; }
/// <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>
bool? BodyAsJsonIndented { get; set; }

View File

@@ -4,7 +4,6 @@
<Description>Commonly used interfaces, models, enumerations and types.</Description>
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>net45;net451;net462;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>-->
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591;8603</NoWarn>

View File

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

View File

@@ -4,7 +4,6 @@
<Description>GraphQL support for WireMock.Net</Description>
<AssemblyTitle>WireMock.Net.Matchers.GraphQL</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0</TargetFrameworks>-->
<TargetFrameworks>net462;netstandard2.1;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;matchers;matcher;graphql</PackageTags>

View File

@@ -38,7 +38,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CS-Script" Version="4.11.0" />
<PackageReference Include="CS-Script" Version="4.13.2" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,6 @@
// Copyright © WireMock.Net
using System;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Admin.Mappings;
using WireMock.Matchers.Request;
@@ -164,8 +161,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

@@ -0,0 +1,49 @@
// Copyright © WireMock.Net
using System;
using JsonConverter.Abstractions;
using Newtonsoft.Json.Linq;
#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER || NET6_0_OR_GREATER || NET461
using System.Text.Json;
#endif
namespace WireMock.Serialization;
internal class MappingSerializer(IJsonConverter jsonConverter)
{
internal T[] DeserializeJsonToArray<T>(string value)
{
return DeserializeObjectToArray<T>(jsonConverter.Deserialize<object>(value)!);
}
internal static T[] DeserializeObjectToArray<T>(object value)
{
if (value is JArray jArray)
{
return jArray.ToObject<T[]>()!;
}
if (value is JObject jObject)
{
var singleResult = jObject.ToObject<T>();
return [singleResult!];
}
#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER || NET6_0_OR_GREATER || NET461
if (value is JsonElement jElement)
{
if (jElement.ValueKind == JsonValueKind.Array)
{
return jElement.Deserialize<T[]>()!;
}
if (jElement.ValueKind == JsonValueKind.Object)
{
var singleResult = jElement.Deserialize<T>();
return [singleResult!];
}
}
#endif
throw new InvalidOperationException("Cannot deserialize the provided value to an array or object.");
}
}

View File

@@ -2,7 +2,8 @@
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using JsonConverter.Abstractions;
using JsonConverter.Newtonsoft.Json;
using Stef.Validation;
using WireMock.Settings;
@@ -12,12 +13,15 @@ internal class MappingToFileSaver
{
private readonly WireMockServerSettings _settings;
private readonly MappingConverter _mappingConverter;
private readonly IJsonConverter _jsonConverter;
private readonly MappingFileNameSanitizer _fileNameSanitizer;
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
{
_settings = Guard.NotNull(settings);
_mappingConverter = Guard.NotNull(mappingConverter);
_jsonConverter = settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter();
_fileNameSanitizer = new MappingFileNameSanitizer(settings);
}
@@ -56,6 +60,8 @@ internal class MappingToFileSaver
{
_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

@@ -5,8 +5,8 @@ using System.Linq;
using System.Net;
using System.Text;
using JetBrains.Annotations;
using JsonConverter.Abstractions;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Admin.Mappings;
@@ -235,7 +235,7 @@ public partial class WireMockServer
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
{
var mappingModels = DeserializeJsonToArray<MappingModel>(value);
var mappingModels = _mappingSerializer.DeserializeJsonToArray<MappingModel>(value);
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
{
ConvertMappingAndRegisterAsRespondProvider(mappingModels[0], guidFromFilename, path);
@@ -823,25 +823,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
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues : JsonSerializationConstants.JsonSerializerSettingsDefault)
BodyAsString = _settings.DefaultJsonSerializer.Serialize(result!, jsonOptions)
},
StatusCode = statusCode ?? (int)HttpStatusCode.OK,
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)
{
return new ResponseMessage
@@ -856,6 +862,18 @@ public partial class WireMockServer
};
}
private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
{
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json && requestMessage.BodyData.BodyAsJson != null)
{
var bodyAsJson = requestMessage.BodyData.BodyAsJson!;
return MappingSerializer.DeserializeObjectToArray<T>(bodyAsJson);
}
throw new NotSupportedException();
}
private static T DeserializeObject<T>(IRequestMessage requestMessage) where T : new()
{
switch (requestMessage.BodyData?.DetectedBodyType)
@@ -871,32 +889,4 @@ public partial class WireMockServer
throw new NotSupportedException();
}
}
private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
{
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json && requestMessage.BodyData.BodyAsJson != null)
{
var bodyAsJson = requestMessage.BodyData.BodyAsJson;
return DeserializeObjectToArray<T>(bodyAsJson);
}
throw new NotSupportedException();
}
private static T[] DeserializeJsonToArray<T>(string value)
{
return DeserializeObjectToArray<T>(JsonUtils.DeserializeObject(value));
}
private static T[] DeserializeObjectToArray<T>(object value)
{
if (value is JArray jArray)
{
return jArray.ToObject<T[]>()!;
}
var singleResult = ((JObject)value).ToObject<T>();
return [singleResult!];
}
}

View File

@@ -32,7 +32,7 @@ public partial class WireMockServer
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
{
var mappings = DeserializeJsonToArray<OrgMapping>(value);
var mappings = _mappingSerializer.DeserializeJsonToArray<OrgMapping>(value);
foreach (var mapping in mappings)
{
if (mappings.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))

View File

@@ -11,6 +11,7 @@ using System.Net.Http;
using System.Threading;
using AnyOfTypes;
using JetBrains.Annotations;
using JsonConverter.Newtonsoft.Json;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Admin.Mappings;
@@ -47,6 +48,7 @@ public partial class WireMockServer : IWireMockServer
private readonly MappingBuilder _mappingBuilder;
private readonly IGuidUtils _guidUtils = new GuidUtils();
private readonly IDateTimeUtils _dateTimeUtils = new DateTimeUtils();
private readonly MappingSerializer _mappingSerializer;
/// <inheritdoc />
[PublicAPI]
@@ -357,6 +359,8 @@ public partial class WireMockServer : IWireMockServer
{
_settings = Guard.NotNull(settings);
_mappingSerializer = new MappingSerializer(settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter());
// Set default values if not provided
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
@@ -631,7 +635,7 @@ public partial class WireMockServer : IWireMockServer
[PublicAPI]
public IWireMockServer WithMapping(string mappings)
{
var mappingModels = DeserializeJsonToArray<MappingModel>(mappings);
var mappingModels = _mappingSerializer.DeserializeJsonToArray<MappingModel>(mappings);
foreach (var mappingModel in mappingModels)
{
ConvertMappingAndRegisterAsRespondProvider(mappingModel, mappingModel.Guid ?? Guid.NewGuid());

View File

@@ -4,7 +4,6 @@
<Description>ProtoBuf and gRPC support for WireMock.Net</Description>
<AssemblyTitle>WireMock.Net.ProtoBuf</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>netstandard2.1;net462;net6.0;net8.0</TargetFrameworks>-->
<TargetFrameworks>net462;netstandard2.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;matchers;matcher;protobuf;grpc</PackageTags>

View File

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

View File

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

View File

@@ -1,20 +1,20 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using HandlebarsDotNet;
using JetBrains.Annotations;
using JsonConverter.Abstractions;
using JsonConverter.Newtonsoft.Json;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using WireMock.Admin.Mappings;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Models;
using WireMock.RegularExpressions;
using WireMock.Types;
using System.Globalization;
using WireMock.Models;
using Microsoft.Extensions.DependencyInjection;
namespace WireMock.Settings;
@@ -148,7 +148,7 @@ public class WireMockServerSettings
[JsonIgnore]
public Action<object>? PostWireMockMiddlewareInit { get; set; }
//#if USE_ASPNETCORE
//#if USE_ASPNETCORE
/// <summary>
/// Action which is called with IServiceCollection when ASP.NET Core DI is being configured. [Optional]
/// </summary>
@@ -161,7 +161,7 @@ public class WireMockServerSettings
/// </summary>
[PublicAPI]
public CorsPolicyOptions? CorsPolicyOptions { get; set; }
//#endif
//#endif
/// <summary>
/// The IWireMockLogger which logs Debug, Info, Warning or Error
@@ -246,7 +246,7 @@ public class WireMockServerSettings
[PublicAPI]
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
//#if USE_ASPNETCORE
//#if USE_ASPNETCORE
/// <summary>
/// Client certificate mode for the server
/// </summary>
@@ -257,7 +257,7 @@ public class WireMockServerSettings
/// Whether to accept any client certificate
/// </summary>
public bool AcceptAnyClientCertificate { get; set; }
//#endif
//#endif
/// <summary>
/// Defines the global IWebhookSettings to use.
@@ -347,6 +347,16 @@ public class WireMockServerSettings
[PublicAPI]
public ActivityTracingOptions? ActivityTracingOptions { get; set; }
/// <summary>
/// Gets or sets the default JSON converter used for serialization.
/// </summary>
/// <remarks>
/// Set this property to customize how objects are serialized to and deserialized from JSON during mapping.
/// Default is <see cref="NewtonsoftJsonConverter"/>.
/// </remarks>
[PublicAPI]
public IJsonConverter DefaultJsonSerializer { get; set; } = new NewtonsoftJsonConverter();
/// <summary>
/// WebSocket settings.
/// </summary>

View File

@@ -2,7 +2,6 @@
<PropertyGroup>
<Description>Shared interfaces, models, enumerations and types.</Description>
<Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>net451;net452;net46;net462;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>-->
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>tdd;mock;http;wiremock;test;server;shared</PackageTags>
@@ -30,9 +29,8 @@
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.9" />
<PackageReference Include="Stef.Validation" Version="0.2.0" />
<PackageReference Include="AnyOf" Version="0.5.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="JsonConverter.Abstractions" Version="0.7.2" />
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -3,7 +3,6 @@
<Description>Lightweight StandAlone Http Mocking Server for .Net.</Description>
<AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>net451;net452;net46;net462;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>-->
<TargetFrameworks>netstandard2.1;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net.StandAlone</AssemblyName>
@@ -29,8 +28,8 @@
</PropertyGroup>
<!-- Enable OpenTelemetry exporter support for .NET 6+ -->
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
<!-- Enable OpenTelemetry exporter support for .NET 8+ -->
<PropertyGroup Condition="' $(TargetFramework)' == 'net8.0' ">
<DefineConstants>$(DefineConstants);OPENTELEMETRY_SUPPORTED</DefineConstants>
</PropertyGroup>
@@ -45,8 +44,8 @@
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
</ItemGroup>
<!-- OpenTelemetry exporter for .NET 6+ -->
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
<!-- OpenTelemetry exporter for .NET 8+ -->
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<ProjectReference Include="..\WireMock.Net.OpenTelemetry\WireMock.Net.OpenTelemetry.csproj" />
</ItemGroup>
</Project>

View File

@@ -3,7 +3,6 @@
<Description>Lightweight Http Mocking Server for .NET, inspired by WireMock from the Java landscape.</Description>
<AssemblyTitle>WireMock.Net</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>net451;net452;net46;net462;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>-->
<TargetFrameworks>net462;netstandard2.1;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net</AssemblyName>