using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using WireMock.Util;
namespace WireMock.Matchers;
///
/// Generic AbstractJsonPartialMatcher
///
public abstract class AbstractJsonPartialMatcher : JsonMatcher
{
///
/// Support Regex
///
public bool Regex { get; }
///
/// Initializes a new instance of the class.
///
/// The string value to check for equality.
/// Ignore the case from the PropertyName and PropertyValue (string only).
/// Support Regex.
protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool regex = false) : base(value, ignoreCase)
{
Regex = regex;
}
///
/// Initializes a new instance of the class.
///
/// The object value to check for equality.
/// Ignore the case from the PropertyName and PropertyValue (string only).
/// Support Regex.
protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool regex = false) : base(value, ignoreCase)
{
Regex = regex;
}
///
/// Initializes a new instance of the class.
///
/// The match behaviour.
/// The value to check for equality.
/// Ignore the case from the PropertyName and PropertyValue (string only).
/// Support Regex.
protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool regex = false) : base(matchBehaviour, value, ignoreCase)
{
Regex = regex;
}
///
protected override bool IsMatch(JToken? value, JToken? input)
{
if (value == null || value == input)
{
return true;
}
if (Regex && value.Type == JTokenType.String && input != null)
{
var valueAsString = value.ToString();
var (valid, result) = RegexUtils.MatchRegex(valueAsString, input.ToString());
if (valid)
{
return result;
}
}
if (input != null &&
((value.Type == JTokenType.Guid && input.Type == JTokenType.String) ||
(value.Type == JTokenType.String && input.Type == JTokenType.Guid)))
{
return IsMatch(value.ToString(), input.ToString());
}
if (input == null || value.Type != input.Type)
{
return false;
}
switch (value.Type)
{
case JTokenType.Object:
var nestedValues = value.ToObject>();
return nestedValues?.Any() != true ||
nestedValues.All(pair => IsMatch(pair.Value, input.SelectToken(pair.Key)));
case JTokenType.Array:
var valuesArray = value.ToObject();
var tokenArray = input.ToObject();
if (valuesArray?.Any() != true)
{
return true;
}
return tokenArray?.Any() == true &&
valuesArray.All(subFilter => tokenArray.Any(subToken => IsMatch(subFilter, subToken)));
default:
return IsMatch(value.ToString(), input.ToString());
}
}
///
/// Check if two strings are a match (matching can be done exact or wildcard)
///
protected abstract bool IsMatch(string value, string input);
}