LinqMatcher and JsonUtils

This commit is contained in:
Stef Heyenrath
2018-09-06 19:25:09 +02:00
parent 9e44f7eb0e
commit f3c395833a
6 changed files with 239 additions and 58 deletions

View File

@@ -1,6 +1,8 @@
using System.Linq;
using System.Linq.Dynamic.Core;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
using WireMock.Util;
namespace WireMock.Matchers
{
@@ -63,29 +65,33 @@ namespace WireMock.Matchers
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
}
///// <inheritdoc cref="IObjectMatcher.IsMatch"/>
//public double IsMatch(object input)
//{
// object value;
// switch (input)
// {
// case JObject valueAsJObject:
// value = valueAsJObject.ToObject<object>();
// break;
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
public double IsMatch(object input)
{
JObject value;
switch (input)
{
case JObject valueAsJObject:
value = valueAsJObject; // valueAsJObject.ToObject<object>();
break;
// default:
// value = input;
// break;
// }
default:
value = JObject.FromObject(input);
break;
}
// // Convert a single object to a Queryable object-list with 1 entry.
// IQueryable queryable = new[] { value }.AsQueryable().Select("new (it as x)");
// Convert a single object to a Queryable JObject-list with 1 entry.
var queryable1 = new[] { value }.AsQueryable();
// // Use the Any(...) method to check if the result matches
// double match = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern)));
// Generate the dynamic linq select statement and generate a dynamic Queryable.
string dynamicSelect = JsonUtils.GenerateDynamicLinqStatement(value);
var queryable2 = queryable1.Select(dynamicSelect);
// return MatchBehaviourHelper.Convert(MatchBehaviour, match);
//}
// Use the Any(...) method to check if the result matches
double match = MatchScores.ToScore(_patterns.Select(pattern => queryable2.Any(pattern)));
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()

View File

@@ -1,4 +1,8 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WireMock.Util
{
@@ -6,12 +10,121 @@ namespace WireMock.Util
{
public static T ParseJTokenToObject<T>(object value)
{
if (value == null)
switch (value)
{
return default(T);
}
case JToken tokenValue:
return tokenValue.ToObject<T>();
return !(value is JToken token) ? default(T) : token.ToObject<T>();
default:
return default(T);
}
}
public static string GenerateDynamicLinqStatement(JObject jsonObject)
{
var lines = new List<string>();
WalkNode(jsonObject, null, null, lines);
return lines.First();
}
private static void WalkNode(JToken node, string path, string propertyName, List<string> lines)
{
if (node.Type == JTokenType.Object)
{
var childLines = new List<string>();
var text = new StringBuilder("new (");
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JProperty child in node.Children<JProperty>().ToArray())
{
WalkNode(child.Value, child.Path, child.Name, childLines);
}
text.Append(string.Join(", ", childLines));
text.Append(")");
if (!string.IsNullOrEmpty(propertyName))
{
text.AppendFormat(" as {0}", propertyName);
}
lines.Add(text.ToString());
}
else if (node.Type == JTokenType.Array)
{
var items = new List<string>();
var text = new StringBuilder("(new [] { ");
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
int idx = 0;
foreach (JToken child in node.Children().ToArray())
{
WalkNode(child, $"{node.Path}[{idx}]", null, items);
idx++;
}
text.Append(string.Join(", ", items));
text.Append("})");
if (!string.IsNullOrEmpty(propertyName))
{
text.AppendFormat(" as {0}", propertyName);
}
lines.Add(text.ToString());
}
else
{
string castText = string.Empty;
switch (node.Type)
{
case JTokenType.Boolean:
castText = $"bool({path})";
break;
case JTokenType.Date:
castText = $"DateTime({path})";
break;
case JTokenType.Float:
castText = $"double({path})";
break;
case JTokenType.Guid:
castText = $"Guid({path})";
break;
case JTokenType.Integer:
castText = $"int({path})";
break;
case JTokenType.Null:
castText = "null";
break;
case JTokenType.String:
castText = $"string({path})";
break;
case JTokenType.TimeSpan:
castText = $"TimeSpan({path})";
break;
case JTokenType.Uri:
castText = $"Uri({path})";
break;
default:
throw new NotSupportedException($"JTokenType '{node.Type}'.");
}
if (!string.IsNullOrEmpty(propertyName))
{
castText += $" as {propertyName}";
}
lines.Add(castText);
}
}
}
}

View File

@@ -49,7 +49,7 @@
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="RestEase" Version="1.4.4" />
<PackageReference Include="MimeKitLite" Version="2.0.1" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.8.17" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.8.18" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">