using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
namespace WireMock.Matchers
{
///
/// JsonPartialMatcher
///
public class JsonPartialMatcher : JsonMatcher
{
///
public override string Name => "JsonPartialMatcher";
///
/// Initializes a new instance of the class.
///
/// The string value to check for equality.
/// Ignore the case from the PropertyName and PropertyValue (string only).
/// Throw an exception when the internal matching fails because of invalid input.
public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException)
{
}
///
/// Initializes a new instance of the class.
///
/// The object value to check for equality.
/// Ignore the case from the PropertyName and PropertyValue (string only).
/// Throw an exception when the internal matching fails because of invalid input.
public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException)
{
}
///
/// 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).
/// Throw an exception when the internal matching fails because of invalid input.
public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(matchBehaviour, value, ignoreCase, throwException)
{
}
///
protected override bool IsMatch(JToken value, JToken input)
{
if (value == null || value == input)
{
return true;
}
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 value.ToString() == input.ToString();
}
}
}
}