public Task BindModelAsync(ModelBindingContext ctx) { var model = ctx.ModelName; JsonParameter res = null; foreach (var key in ctx.HttpContext.Request.Query.Keys.Where(x => x == model || x.StartsWith($"{model}."))) { if (!JsonPath.TryParse(key, out var path)) { ctx.ModelState.AddModelError(key, $"Path contains invalid item: {path.First(x => x.Type == JsonPathType.None).Value}"); return(Task.CompletedTask); } if (path.Any(x => x.Type == JsonPathType.Any) && path.Any(x => x.Type == JsonPathType.Index)) { ctx.ModelState.AddModelError(key, $"Mixed array access is not allowed: [{path.First(x => x.Type == JsonPathType.Index).Value}] and [*]"); return(Task.CompletedTask); } res ??= new JsonParameter(); switch (path[^ 1].Value)
public void Run(ComplianceTestCase testCase) { if (_notSupported.Contains(testCase.Selector)) { Assert.Inconclusive("This case will not be supported."); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine(testCase); Console.WriteLine(); JsonPath path = null; PathResult actual = null; var time = Debugger.IsAttached ? int.MaxValue : 100; using var cts = new CancellationTokenSource(time); Task.Run(() => { if (!JsonPath.TryParse(testCase.Selector, out path)) { return; } if (testCase.Document.ValueKind == JsonValueKind.Undefined) { return; } actual = path.Evaluate(testCase.Document); }, cts.Token).Wait(cts.Token); if (path != null && testCase.InvalidSelector) { Assert.Inconclusive($"{testCase.Selector} is not a valid path but was parsed without error."); } if (actual == null) { if (testCase.InvalidSelector) { return; } Assert.Fail($"Could not parse path: {testCase.Selector}"); } var actualValues = actual.Matches.Select(m => m.Value).AsJsonElement(); Console.WriteLine($"Actual (values): {actualValues}"); Console.WriteLine(); Console.WriteLine($"Actual: {JsonSerializer.Serialize(actual)}"); if (testCase.InvalidSelector) { Assert.Fail($"{testCase.Selector} is not a valid path."); } var expected = testCase.Result.AsJsonElement(); Assert.IsTrue(expected.IsEquivalentTo(actualValues)); }