コード例 #1
0
        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);
        }
コード例 #2
0
 public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression)
 {
     index     += 2;
     expression = new OperatorExpression {
         Operator = JsonPathOperator.LessThanOrEqual
     };
     return(null);
 }
コード例 #3
0
 public string TryParse <TIn>(string source, ref int index, out JsonPathExpression expression)
 {
     index++;
     expression = new OperatorExpression {
         Operator = JsonPathOperator.Subtract
     };
     return(null);
 }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        public void IsAbsolute_StartsWithNonRootElement_ReturnsFalse()
        {
            var path = new JsonPathExpression(new JsonPathElement[]
            {
                new JsonPathPropertyElement("a"),
                new JsonPathArrayIndexElement(42)
            });

            path.IsAbsolute.Should().BeFalse();
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        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);
        }
コード例 #15
0
        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);
        }
コード例 #16
0
        public void IsNormalized_NormalizedElements_ReturnsTrue()
        {
            var path = new JsonPathExpression(new JsonPathElement[]
            {
                new JsonPathRootElement(),
                new JsonPathPropertyElement("a"),
                new JsonPathArrayIndexElement(42)
            });

            path.IsNormalized.Should().BeTrue();
        }
コード例 #17
0
        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);
        }
コード例 #18
0
        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);
        }
コード例 #19
0
        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")
            });
コード例 #20
0
        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);
        }
コード例 #21
0
        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>();
        }
コード例 #22
0
ファイル: Interpreter.cs プロジェクト: stanac/JsonPathway
        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()}");
        }
コード例 #23
0
        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);
        }
コード例 #24
0
        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");
        }
コード例 #25
0
        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);
        }