Update JSONPathMatcher.cs to cover the string path selection to a child (#993)

* Update JSONPathMatcher.cs to cover the string path selection to a child 

The .SelectToken method accept string path selection and JSONPath queries. The current code works only for the queries because the result is JObject. When the string path is selected the result is JValue and event with a valid result the code the code doesn't return valued result.
https://www.newtonsoft.com/json/help/html/SelectToken.htm

* Added unit tests

* Addressed the comments

* Addressed the comments

* Update JSONPathMatcher.cs
This commit is contained in:
DayLightDancer
2023-08-17 18:18:32 +03:00
committed by GitHub
parent fd816f0952
commit 8adf34fb56
2 changed files with 132 additions and 3 deletions

View File

@@ -123,7 +123,12 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
{
var array = ConvertJTokenToJArrayIfNeeded(jToken);
return MatchScores.ToScore(_patterns.Select(pattern => array.SelectToken(pattern.GetPattern())?.Any() == true).ToArray(), MatchOperator);
// The SelectToken method can accept a string path to a child token ( i.e. "Manufacturers[0].Products[0].Price"). In that case it will return a JValue (some type) which does not implement the IEnumerable interface.
// Using ?.Any() == true relays that we use a JSONPath queries and the SelectToken will return a JObject ( implements the IEnumerable interface).
// So the current code works only when the JSONPath is expression and not when we pass a valid string path to child.
// My suggestion is to roll back to != null to cover the both cases.
return MatchScores.ToScore(_patterns.Select(pattern => array.SelectToken(pattern.GetPattern()) != null ).ToArray(), MatchOperator);
}
// https://github.com/WireMock-Net/WireMock.Net/issues/965
@@ -149,4 +154,4 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
return jToken;
}
}
}

View File

@@ -200,4 +200,128 @@ public class JsonPathMatcherTests
// Assert
Check.That(match).IsEqualTo(0.0);
}
}
[Fact]
public void JsonPathMatcher_IsMatch_ArrayOneLevel()
{
// Arrange
var matcher = new JsonPathMatcher("$.arr[0].line1");
// Act
double match = matcher.IsMatch(JObject.Parse(@"{
""name"": ""PathSelectorTest"",
""test"": ""test"",
""test2"": ""test2"",
""arr"": [{
""line1"": ""line1"",
}]
}"));
// Assert
Check.That(match).IsEqualTo(1.0);
}
[Fact]
public void JsonPathMatcher_IsMatch_ObjectMatch()
{
// Arrange
var matcher = new JsonPathMatcher("$.test");
// Act
double match = matcher.IsMatch(JObject.Parse(@"{
""name"": ""PathSelectorTest"",
""test"": ""test"",
""test2"": ""test2"",
""arr"": [
{
""line1"": ""line1"",
}
]
}"));
// Assert
Check.That(match).IsEqualTo(1.0);
}
[Fact]
public void JsonPathMatcher_IsMatch_DoesntMatch()
{
// Arrange
var matcher = new JsonPathMatcher("$.test3");
// Act
double match = matcher.IsMatch(JObject.Parse(@"{
""name"": ""PathSelectorTest"",
""test"": ""test"",
""test2"": ""test2"",
""arr"": [
{
""line1"": ""line1"",
}
]
}"));
// Assert
Check.That(match).IsEqualTo(0.0);
}
[Fact]
public void JsonPathMatcher_IsMatch_DoesntMatchInArray()
{
// Arrange
var matcher = new JsonPathMatcher("$arr[0].line1");
// Act
double match = matcher.IsMatch(JObject.Parse(@"{
""name"": ""PathSelectorTest"",
""test"": ""test"",
""test2"": ""test2"",
""arr"": []
}"));
// Assert
Check.That(match).IsEqualTo(0.0);
}
[Fact]
public void JsonPathMatcher_IsMatch_DoesntMatchNoObjectsInArray()
{
// Arrange
var matcher = new JsonPathMatcher("$arr[2].line1");
// Act
double match = matcher.IsMatch(JObject.Parse(@"{
""name"": ""PathSelectorTest"",
""test"": ""test"",
""test2"": ""test2"",
""arr"": []
}"));
// Assert
Check.That(match).IsEqualTo(0.0);
}
[Fact]
public void JsonPathMatcher_IsMatch_NestedArrays()
{
// Arrange
var matcher = new JsonPathMatcher("$.arr[0].sub[0].subline1");
// Act
double match = matcher.IsMatch(JObject.Parse(@"{
""name"": ""PathSelectorTest"",
""test"": ""test"",
""test2"": ""test2"",
""arr"": [{
""line1"": ""line1"",
""sub"":[
{
""subline1"":""subline1""
}]
}]
}"));
// Assert
Check.That(match).IsEqualTo(1.0);
}
}