public void Build_Builds() { var expected = new JsonPathExpression(new JsonPathElement[] { new JsonPathRootElement(), new JsonPathRecursiveDescentElement(new JsonPathPropertyElement("a")), new JsonPathAnyPropertyElement(), new JsonPathPropertyListElement(new [] { "b", "c" }), new JsonPathArrayIndexElement(42), new JsonPathAnyArrayIndexElement(), new JsonPathArrayIndexListElement(new [] { 7, 42 }), new JsonPathArraySliceElement(0, 42, 2), new JsonPathExpressionElement("@.length-1"), new JsonPathFilterExpressionElement("@.name = 'a'") }); var actual = JsonPathExpressionBuilder.Create() .Root() .RecursiveDescentTo().Property("a") .AnyProperty() .Properties("b", "c") .ArrayIndex(42) .AnyArrayIndex() .ArrayIndexes(7, 42) .ArraySlice(0, 42, 2) .Expression("@.length-1") .FilterExpression("@.name = 'a'") .Build(); actual.Should().BeEquivalentTo(expected); }
public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression) { index += 2; expression = new OperatorExpression { Operator = JsonPathOperator.LessThanOrEqual }; return(null); }
public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression) { index++; expression = new OperatorExpression { Operator = JsonPathOperator.Subtract }; return(null); }
public void RemoveLast(string path, int count, string expected) { var pathExpr = new JsonPathExpression(path); var expectedExpr = new JsonPathExpression(expected); var actual = pathExpr.RemoveLast(count); actual.Should().BeEquivalentTo(expectedExpr); }
public void StartsWith(string path, string prefixPath, bool expected) { var pathExpr = new JsonPathExpression(path); var prefixPathExpr = new JsonPathExpression(prefixPath); bool actual = pathExpr.StartsWith(prefixPathExpr); actual.Should().Be(expected); }
public void Matches(string path, string other, bool?expected) { var pathExpr = new JsonPathExpression(path); var otherExpr = new JsonPathExpression(other); bool?actual = pathExpr.Matches(otherExpr); actual.Should().Be(expected); }
public void ToAbsolute(string path, string expected) { var pathExpr = new JsonPathExpression(path); var expectedExpr = new AbsoluteJsonPathExpression(expected); var actual = pathExpr.ToAbsolute(); actual.Should().BeEquivalentTo(expectedExpr); }
public void GetNormalized(string path, string expected) { var pathExpr = new JsonPathExpression(path); var expectedExpr = new JsonPathExpression(expected); var actual = pathExpr.GetNormalized(); actual.Should().BeEquivalentTo(expectedExpr); }
public void Equals_ReturnsExpected(string first, string second, bool expected) { var firstPath = new JsonPathExpression(first); var secondPath = new JsonPathExpression(second); bool actual = firstPath.Equals(secondPath); actual.Should().Be(expected); }
public void IsAbsolute_StartsWithNonRootElement_ReturnsFalse() { var path = new JsonPathExpression(new JsonPathElement[] { new JsonPathPropertyElement("a"), new JsonPathArrayIndexElement(42) }); path.IsAbsolute.Should().BeFalse(); }
public void GetParentWith(string path, string other, string expected) { var pathExpr = new JsonPathExpression(path); var otherExpr = new JsonPathExpression(other); var expectedExpr = expected != null ? new JsonPathExpression(expected) : null; var actual = pathExpr.GetParentWith(otherExpr); actual.Should().BeEquivalentTo(expectedExpr); }
public void GetRelativePathTo(string path, string child, string expected) { var pathExpr = new JsonPathExpression(path); var childExpr = new JsonPathExpression(child); var expectedExpr = expected != null ? new RelativeJsonPathExpression(expected) : null; var actual = pathExpr.GetRelativePathTo(childExpr); actual.Should().BeEquivalentTo(expectedExpr); }
public void ReplaceLastWith_Replaces() { var path = new JsonPathExpression(new JsonPathElement[] { new JsonPathRootElement(), new JsonPathPropertyElement("a") }); var element = new JsonPathPropertyElement("b"); var expected = new JsonPathExpression(new JsonPathElement[] { new JsonPathRootElement(), element }); var actual = path.ReplaceLastWith(element); actual.Should().BeEquivalentTo(expected); }
public void Append_RelativeJsonPathExpression(string path, string relativePath, string expected) { var pathExpr = new JsonPathExpression(path); var relativePathExpr = new RelativeJsonPathExpression(relativePath); var expectedExpr = new JsonPathExpression(expected); var actual = pathExpr.Append(relativePathExpr); actual.Should().BeEquivalentTo(expectedExpr); }
public void Expression_UsedMultipleTimes_ReturnsSameResult() { string path = "$.store.bicycle.color.length"; ExpressionList expression = JsonPathExpression.Parse(path); JsonDocument doc = JsonDocument.Parse(_json); JsonElement result1 = JsonPath.ExecutePath(expression, doc).Single(); JsonElement result2 = JsonPath.ExecutePath(expression, doc).Single(); Assert.Equal(result1, result2, JsonElementEqualityComparer.Default); }
public void IsNormalized_NormalizedElements_ReturnsTrue() { var path = new JsonPathExpression(new JsonPathElement[] { new JsonPathRootElement(), new JsonPathPropertyElement("a"), new JsonPathArrayIndexElement(42) }); path.IsNormalized.Should().BeTrue(); }
public void Append_Elements(string path, string expected, params string[] elementsToAppend) { var pathExpr = new JsonPathExpression(path); var expectedExpr = new JsonPathExpression(expected); var elements = elementsToAppend .Select(x => JsonPathExpressionStringParser.Parse(x).First()) .ToArray(); var actual = pathExpr.Append(elements); actual.Should().BeEquivalentTo(expectedExpr); }
public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression) { if (source[index] == ']') { expression = null; return(null); } index += 1; expression = new OperatorExpression { Operator = JsonPathOperator.GroupEnd }; return(null); }
private static ExpressionTreeNode <TIn> _Visit <TIn>(JsonPathExpression expr) { if (expr is PathValueExpression <TIn> path) { return(path.Path); } if (expr is ValueExpression value) { return(new ValueExpression <TIn>(value.Value)); } if (!(expr is OperatorExpression op)) { throw new NotSupportedException($"Expressions of type {expr.GetType()} are not supported."); } var left = _Visit <TIn>(op.Children[0]); if (op.Operator == JsonPathOperator.Negate) { return(_VisitNegate(left)); } if (op.Operator == JsonPathOperator.Not) { return(new NotExpression <TIn>(_MakeHasPropertyIfNameExpression(left))); } var right = _Visit <TIn>(op.Children.Count > 1 ? op.Children[1] : throw new InvalidOperationException($"Operator type {op.Operator} requires two operands.")); _CheckAndReplaceIfHasPropertyNeeded(op.Operator, ref left, ref right); return(op.Operator switch { JsonPathOperator.Add => (ExpressionTreeNode <TIn>) new AddExpression <TIn>(left, right), JsonPathOperator.And => new AndExpression <TIn>(left, right), JsonPathOperator.Divide => new DivideExpression <TIn>(left, right), JsonPathOperator.Exponent => new ExponentExpression <TIn>(left, right), JsonPathOperator.Equal => new IsEqualExpression <TIn>(left, right), JsonPathOperator.GreaterThan => new IsGreaterThanExpression <TIn>(left, right), JsonPathOperator.GreaterThanOrEqual => new IsGreaterThanEqualExpression <TIn>(left, right), JsonPathOperator.LessThan => new IsLessThanExpression <TIn>(left, right), JsonPathOperator.LessThanOrEqual => new IsLessThanEqualExpression <TIn>(left, right), JsonPathOperator.NotEqual => new IsNotEqualExpression <TIn>(left, right), JsonPathOperator.Modulo => new ModuloExpression <TIn>(left, right), JsonPathOperator.Multiply => new MultiplyExpression <TIn>(left, right), JsonPathOperator.Subtract => new SubtractExpression <TIn>(left, right), JsonPathOperator.Or => new OrExpression <TIn>(left, right), _ => throw new NotSupportedException($"Expressions of type {expr.GetType()} are not supported") });
public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression) { expression = null; var error = source.GetKey(ref index, out var value); if (error != null) { return(error); } expression = new ValueExpression { Value = value }; return(null); }
public void Create_ReturnsObjectOfTheSameType() { var path = new JsonPathExpression(new JsonPathElement[] { new JsonPathRootElement() }); var elements = new JsonPathElement[] { new JsonPathRootElement(), new JsonPathPropertyElement("a"), new JsonPathArrayIndexElement(42) }; var actual = path.Create(elements); actual.Elements.Should().BeEquivalentTo(elements); actual.GetType().Should().Be <JsonPathExpression>(); }
internal static IEnumerable <JsonElement> ExecuteInternal(JsonPathExpression expression, JsonElement element) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } switch (expression) { case PropertyAccessExpression pae: return(ExecuteInternal(pae, element)); case ArrayElementsExpression aee: return(ExecuteInternal(aee, element)); case FilterExpression fe: return(ExecuteInternal(fe, element)); } throw new ArgumentOutOfRangeException($"No interpreter implementation found for {expression.GetType()}"); }
public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression) { expression = null; if (source[index] == 't') { index += 4; expression = new ValueExpression { Value = true }; } else if (source[index] == 'f') { index += 5; expression = new ValueExpression { Value = false }; } else { return("Boolean value not recoginized."); } return(null); }
private ExpressionTreeNode <TIn> _Visit <TIn>(JsonPathExpression expr) { if (expr is null) { return(null); } if (expr is PathValueExpression <TIn> path) { return(path.Path); } if (expr is ValueExpression value) { return new ValueExpression <TIn> { Value = value.Value } } ; if (!(expr is OperatorExpression op)) { throw new NotSupportedException($"Expressions of type {expr.GetType()} are not supported"); } var left = _Visit <TIn>(op.Children[0]); var right = _Visit <TIn>(op.Children.Count > 1 ? op.Children[1] : null); _CheckAndReplaceIfHasPropertyNeeded(op.Operator, ref left, ref right); switch (op.Operator) { case JsonPathOperator.Add: return(new AddExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.And: return(new AndExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Divide: return(new DivideExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Exponent: return(new ExponentExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Equal: return(new IsEqualExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.GreaterThan: return(new IsGreaterThanExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.GreaterThanOrEqual: return(new IsGreaterThanEqualExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.LessThan: return(new IsLessThanExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.LessThanOrEqual: return(new IsLessThanEqualExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.NotEqual: return(new IsNotEqualExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Modulo: return(new ModuloExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Multiply: return(new MultiplyExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Subtract: return(new SubtractExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Or: return(new OrExpression <TIn> { Left = left, Right = right, }); case JsonPathOperator.Negate: return(_VisitNegate(left)); case JsonPathOperator.Not: return(new NotExpression <TIn> { Root = _MakeHasPropertyIfNameExpression(left) }); } throw new NotSupportedException($"Expressions of type {expr.GetType()} are not supported"); }
public string TryParse <T>(string source, ref int index, out JsonPathExpression expression) { expression = null; PathExpression <T> node; var isLocal = source[index] == '@'; var error = JsonPathParser.Parse(source, ref index, out JsonPath path); // Swallow this error from the path parser and assume the path just ended. // If it's really a syntax error, the expression parser should catch it. if (error != null && error != "Unrecognized JSON Path element.") { return(error); } var lastOp = path.Operators.Last(); if (lastOp is NameOperator name) { path.Operators.Remove(name); if (name.Name == "indexOf") { if (source[index] != '(') { return("Expected '('. 'indexOf' operator requires a parameter."); } index++; error = JsonParser.Parse(source, ref index, out JsonValue parameter, true); // Swallow this error from the JSON parser and assume the value just ended. // If it's really a syntax error, the expression parser should catch it. if (error != null && error != "Expected \',\', \']\', or \'}\'.") { return($"Error parsing parameter for 'indexOf' expression: {error}."); } if (source[index] != ')') { return("Expected ')'."); } index++; node = new IndexOfExpression <T> { Path = path, IsLocal = isLocal, Parameter = parameter }; } else { node = new NameExpression <T> { Path = path, IsLocal = isLocal, Name = name.Name } }; } else if (lastOp is LengthOperator length) { path.Operators.Remove(length); node = new LengthExpression <T> { Path = path, IsLocal = isLocal }; } else if (lastOp is ArrayOperator array) { path.Operators.Remove(array); var query = array.Query as SliceQuery; var constant = query?.Slices.FirstOrDefault()?.Index; if (query == null || query.Slices.Count() != 1 || !constant.HasValue) { return("JSON Path expression indexers only support single constant values."); } node = new ArrayIndexExpression <T> { Path = path, IsLocal = isLocal, Index = constant.Value }; } else { throw new NotImplementedException(); } expression = new PathValueExpression <T> { Path = node }; return(null); }