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(); } } } }