Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonMatcher support IgnoreCase #333

Merged
merged 3 commits into from
Aug 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions WireMock.Net Solution.sln
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.Net
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Service", "examples\Wiremock.Net.Service\WireMock.Net.Service.csproj", "{7F0B2446-0363-4720-AF46-F47F83B557DC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.HeadersTest", "examples\WireMock.Net.Console.HeadersTest\WireMock.Net.Console.HeadersTest.csproj", "{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net461.Classic", "examples\WireMock.Net.Console.Net461.Classic\WireMock.Net.Console.Net461.Classic.csproj", "{1261BB9B-A7D4-456C-8985-3CE560361B8E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net452.Classic", "examples\WireMock.Net.Console.Net452.Classic\WireMock.Net.Console.Net452.Classic.csproj", "{668F689E-57B4-422E-8846-C0FF643CA268}"
Expand Down Expand Up @@ -120,10 +118,6 @@ Global
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.Build.0 = Release|Any CPU
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Release|Any CPU.Build.0 = Release|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -154,7 +148,6 @@ Global
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{7F0B2446-0363-4720-AF46-F47F83B557DC} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{1261BB9B-A7D4-456C-8985-3CE560361B8E} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{668F689E-57B4-422E-8846-C0FF643CA268} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{83645809-9E01-4E81-8733-BA9497554ABF} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
Expand Down
60 changes: 0 additions & 60 deletions examples/WireMock.Net.Console.HeadersTest/Program.cs

This file was deleted.

This file was deleted.

20 changes: 0 additions & 20 deletions examples/WireMock.Net.Console.HeadersTest/log4net.config

This file was deleted.

18 changes: 0 additions & 18 deletions examples/WireMock.Net.Console.HeadersTest/nlog.config

This file was deleted.

72 changes: 65 additions & 7 deletions src/WireMock.Net/Matchers/JsonMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using JetBrains.Annotations;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WireMock.Validation;
Expand All @@ -8,7 +9,7 @@ namespace WireMock.Matchers
/// <summary>
/// JsonMatcher
/// </summary>
public class JsonMatcher : IValueMatcher
public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher
{
/// <inheritdoc cref="IValueMatcher.Value"/>
public object Value { get; }
Expand All @@ -19,19 +20,24 @@ public class JsonMatcher : IValueMatcher
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; }

/// <inheritdoc cref="IIgnoreCaseMatcher.IgnoreCase"/>
public bool IgnoreCase { get; }

/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="value">The string value to check for equality.</param>
public JsonMatcher([NotNull] string value) : this(MatchBehaviour.AcceptOnMatch, value)
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
public JsonMatcher([NotNull] string value, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="value">The object value to check for equality.</param>
public JsonMatcher([NotNull] object value) : this(MatchBehaviour.AcceptOnMatch, value)
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
public JsonMatcher([NotNull] object value, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase)
{
}

Expand All @@ -40,25 +46,29 @@ public JsonMatcher([NotNull] object value) : this(MatchBehaviour.AcceptOnMatch,
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The string value to check for equality.</param>
public JsonMatcher(MatchBehaviour matchBehaviour, [NotNull] string value)
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
public JsonMatcher(MatchBehaviour matchBehaviour, [NotNull] string value, bool ignoreCase = false)
{
Check.NotNull(value, nameof(value));

MatchBehaviour = matchBehaviour;
Value = value;
IgnoreCase = ignoreCase;
}

/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The object value to check for equality.</param>
public JsonMatcher(MatchBehaviour matchBehaviour, [NotNull] object value)
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
public JsonMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false)
{
Check.NotNull(value, nameof(value));

MatchBehaviour = matchBehaviour;
Value = value;
IgnoreCase = ignoreCase;
}

/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
Expand Down Expand Up @@ -91,7 +101,7 @@ public double IsMatch(object input)
break;
}

match = JToken.DeepEquals(jtokenValue, jtokenInput);
match = DeepEquals(jtokenValue, jtokenInput);
}
catch (JsonException)
{
Expand All @@ -101,5 +111,53 @@ public double IsMatch(object input)

return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match));
}

private bool DeepEquals(JToken value, JToken input)
{
if (!IgnoreCase)
{
return JToken.DeepEquals(value, input);
}

JToken renamedValue = Rename(value);
JToken renamedInput = Rename(input);

return JToken.DeepEquals(renamedValue, renamedInput);
}

private static string ToUpper(string input)
{
return input?.ToUpperInvariant();
}

// https://stackoverflow.com/questions/11679804/json-net-rename-properties
private static JToken Rename(JToken json)
{
if (json is JProperty property)
{
JToken propertyValue = property.Value;
if (propertyValue.Type == JTokenType.String)
{
string stringValue = propertyValue.Value<string>();
propertyValue = ToUpper(stringValue);
}

return new JProperty(ToUpper(property.Name), Rename(propertyValue));
}

if (json is JArray array)
{
var renamedValues = array.Select(Rename);
return new JArray(renamedValues);
}

if (json is JObject obj)
{
var renamedProperties = obj.Properties().Select(Rename);
return new JObject(renamedProperties);
}

return json;
}
}
}
2 changes: 1 addition & 1 deletion src/WireMock.Net/Serialization/MatcherMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public IMatcher Map([CanBeNull] MatcherModel matcher)
return new RegexMatcher(matchBehaviour, stringPatterns, matcher.IgnoreCase == true);

case "JsonMatcher":
return new JsonMatcher(matchBehaviour, matcher.Pattern);
return new JsonMatcher(matchBehaviour, matcher.Pattern, matcher.IgnoreCase == true);

case "JsonPathMatcher":
return new JsonPathMatcher(matchBehaviour, stringPatterns);
Expand Down
54 changes: 52 additions & 2 deletions test/WireMock.Net.Tests/Matchers/JsonMatcherTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void JsonMatcher_IsMatch_NullObject()
}

[Fact]
public void JsonMatcher_IsMatch_JObject1()
public void JsonMatcher_IsMatch_JObject()
{
// Assign
var matcher = new JsonMatcher(new { Id = 1, Name = "Test" });
Expand All @@ -94,7 +94,25 @@ public void JsonMatcher_IsMatch_JObject1()
}

[Fact]
public void JsonMatcher_IsMatch_JObject2()
public void JsonMatcher_IsMatch_WithIgnoreCaseTrue_JObject()
{
// Assign
var matcher = new JsonMatcher(new { id = 1, Name = "test" }, true);

// Act
var jobject = new JObject
{
{ "Id", new JValue(1) },
{ "NaMe", new JValue("Test") }
};
double match = matcher.IsMatch(jobject);

// Assert
Assert.Equal(1.0, match);
}

[Fact]
public void JsonMatcher_IsMatch_JObjectParsed()
{
// Assign
var matcher = new JsonMatcher(new { Id = 1, Name = "Test" });
Expand All @@ -107,6 +125,20 @@ public void JsonMatcher_IsMatch_JObject2()
Assert.Equal(1.0, match);
}

[Fact]
public void JsonMatcher_IsMatch_WithIgnoreCaseTrue_JObjectParsed()
{
// Assign
var matcher = new JsonMatcher(new { Id = 1, Name = "TESt" }, true);

// Act
var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }");
double match = matcher.IsMatch(jobject);

// Assert
Assert.Equal(1.0, match);
}

[Fact]
public void JsonMatcher_IsMatch_JObjectAsString()
{
Expand All @@ -125,6 +157,24 @@ public void JsonMatcher_IsMatch_JObjectAsString()
Assert.Equal(1.0, match);
}

[Fact]
public void JsonMatcher_IsMatch_WithIgnoreCaseTrue_JObjectAsString()
{
// Assign
var matcher = new JsonMatcher("{ \"Id\" : 1, \"Name\" : \"test\" }", true);

// Act
var jobject = new JObject
{
{ "Id", new JValue(1) },
{ "Name", new JValue("Test") }
};
double match = matcher.IsMatch(jobject);

// Assert
Assert.Equal(1.0, match);
}

[Fact]
public void JsonMatcher_IsMatch_JObjectAsString_RejectOnMatch()
{
Expand Down