aeson-jsonpath 0.3.0.1 → 0.3.0.2
raw patch · 34 files changed
+14866/−12788 lines, 34 filesdep ~aesondep ~basedep ~template-haskellPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: aeson, base, template-haskell
API changes (from Hackage documentation)
- Data.Aeson.JSONPath.Query: class Queryable a
- Data.Aeson.JSONPath.Query: instance Data.Aeson.JSONPath.Query.Queryable Data.Aeson.JSONPath.Query.Types.Query
- Data.Aeson.JSONPath.Query: instance Data.Aeson.JSONPath.Query.Queryable Data.Aeson.JSONPath.Query.Types.QuerySegment
- Data.Aeson.JSONPath.Query: instance Data.Aeson.JSONPath.Query.Queryable Data.Aeson.JSONPath.Query.Types.Segment
- Data.Aeson.JSONPath.Query: instance Data.Aeson.JSONPath.Query.Queryable Data.Aeson.JSONPath.Query.Types.Selector
- Data.Aeson.JSONPath.Query: query' :: Queryable a => a -> Value -> Value -> Vector Value
- Data.Aeson.JSONPath.Query: queryLocated' :: Queryable a => a -> Value -> Value -> String -> Vector (String, Value)
- Data.Aeson.JSONPath.Query.Types: ArraySlice :: (Maybe Int, Maybe Int, Int) -> Selector
- Data.Aeson.JSONPath.Query.Types: Bracketed :: [Selector] -> Segment
- Data.Aeson.JSONPath.Query.Types: Child :: SegmentType
- Data.Aeson.JSONPath.Query.Types: Comp :: Comparable -> ComparisonOp -> Comparable -> ComparisonExpr
- Data.Aeson.JSONPath.Query.Types: CompLitBool :: Bool -> Comparable
- Data.Aeson.JSONPath.Query.Types: CompLitNull :: Comparable
- Data.Aeson.JSONPath.Query.Types: CompLitNum :: Scientific -> Comparable
- Data.Aeson.JSONPath.Query.Types: CompLitString :: Text -> Comparable
- Data.Aeson.JSONPath.Query.Types: CompSQ :: SingularQuery -> Comparable
- Data.Aeson.JSONPath.Query.Types: Comparison :: ComparisonExpr -> BasicExpr
- Data.Aeson.JSONPath.Query.Types: Current :: QueryType
- Data.Aeson.JSONPath.Query.Types: CurrentSQ :: SingularQueryType
- Data.Aeson.JSONPath.Query.Types: Descendant :: SegmentType
- Data.Aeson.JSONPath.Query.Types: Dotted :: Text -> Segment
- Data.Aeson.JSONPath.Query.Types: Equal :: ComparisonOp
- Data.Aeson.JSONPath.Query.Types: Filter :: LogicalOrExpr -> Selector
- Data.Aeson.JSONPath.Query.Types: Greater :: ComparisonOp
- Data.Aeson.JSONPath.Query.Types: GreaterOrEqual :: ComparisonOp
- Data.Aeson.JSONPath.Query.Types: Index :: Int -> Selector
- Data.Aeson.JSONPath.Query.Types: IndexSQSeg :: Int -> SingularQuerySegment
- Data.Aeson.JSONPath.Query.Types: Less :: ComparisonOp
- Data.Aeson.JSONPath.Query.Types: LessOrEqual :: ComparisonOp
- Data.Aeson.JSONPath.Query.Types: LogicalAnd :: [BasicExpr] -> LogicalAndExpr
- Data.Aeson.JSONPath.Query.Types: LogicalOr :: [LogicalAndExpr] -> LogicalOrExpr
- Data.Aeson.JSONPath.Query.Types: Name :: Text -> Selector
- Data.Aeson.JSONPath.Query.Types: NameSQSeg :: Text -> SingularQuerySegment
- Data.Aeson.JSONPath.Query.Types: NotEqual :: ComparisonOp
- Data.Aeson.JSONPath.Query.Types: NotParen :: LogicalOrExpr -> BasicExpr
- Data.Aeson.JSONPath.Query.Types: NotTest :: TestExpr -> BasicExpr
- Data.Aeson.JSONPath.Query.Types: Paren :: LogicalOrExpr -> BasicExpr
- Data.Aeson.JSONPath.Query.Types: Query :: QueryType -> [QuerySegment] -> Query
- Data.Aeson.JSONPath.Query.Types: QuerySegment :: SegmentType -> Segment -> QuerySegment
- Data.Aeson.JSONPath.Query.Types: Root :: QueryType
- Data.Aeson.JSONPath.Query.Types: RootSQ :: SingularQueryType
- Data.Aeson.JSONPath.Query.Types: SingularQuery :: SingularQueryType -> [SingularQuerySegment] -> SingularQuery
- Data.Aeson.JSONPath.Query.Types: Test :: TestExpr -> BasicExpr
- Data.Aeson.JSONPath.Query.Types: WildcardSegment :: Segment
- Data.Aeson.JSONPath.Query.Types: WildcardSelector :: Selector
- Data.Aeson.JSONPath.Query.Types: [querySegments] :: Query -> [QuerySegment]
- Data.Aeson.JSONPath.Query.Types: [queryType] :: Query -> QueryType
- Data.Aeson.JSONPath.Query.Types: [segmentType] :: QuerySegment -> SegmentType
- Data.Aeson.JSONPath.Query.Types: [segment] :: QuerySegment -> Segment
- Data.Aeson.JSONPath.Query.Types: [singularQuerySegments] :: SingularQuery -> [SingularQuerySegment]
- Data.Aeson.JSONPath.Query.Types: [singularQueryType] :: SingularQuery -> SingularQueryType
- Data.Aeson.JSONPath.Query.Types: data BasicExpr
- Data.Aeson.JSONPath.Query.Types: data Comparable
- Data.Aeson.JSONPath.Query.Types: data ComparisonExpr
- Data.Aeson.JSONPath.Query.Types: data ComparisonOp
- Data.Aeson.JSONPath.Query.Types: data Query
- Data.Aeson.JSONPath.Query.Types: data QuerySegment
- Data.Aeson.JSONPath.Query.Types: data QueryType
- Data.Aeson.JSONPath.Query.Types: data Segment
- Data.Aeson.JSONPath.Query.Types: data SegmentType
- Data.Aeson.JSONPath.Query.Types: data Selector
- Data.Aeson.JSONPath.Query.Types: data SingularQuery
- Data.Aeson.JSONPath.Query.Types: data SingularQuerySegment
- Data.Aeson.JSONPath.Query.Types: data SingularQueryType
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.BasicExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.Comparable
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.ComparisonExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.ComparisonOp
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.LogicalAndExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.LogicalOrExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.Query
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.QuerySegment
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.QueryType
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.Segment
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.SegmentType
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.Selector
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.SingularQuery
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.SingularQuerySegment
- Data.Aeson.JSONPath.Query.Types: instance GHC.Classes.Eq Data.Aeson.JSONPath.Query.Types.SingularQueryType
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.BasicExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.Comparable
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.ComparisonExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.ComparisonOp
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.LogicalAndExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.LogicalOrExpr
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.Query
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.QuerySegment
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.QueryType
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.Segment
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.SegmentType
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.Selector
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.SingularQuery
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.SingularQuerySegment
- Data.Aeson.JSONPath.Query.Types: instance GHC.Show.Show Data.Aeson.JSONPath.Query.Types.SingularQueryType
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.BasicExpr
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.Comparable
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.ComparisonExpr
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.ComparisonOp
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.LogicalAndExpr
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.LogicalOrExpr
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.Query
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.QuerySegment
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.QueryType
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.Segment
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.SegmentType
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.Selector
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.SingularQuery
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.SingularQuerySegment
- Data.Aeson.JSONPath.Query.Types: instance Language.Haskell.TH.Syntax.Lift Data.Aeson.JSONPath.Query.Types.SingularQueryType
- Data.Aeson.JSONPath.Query.Types: newtype LogicalAndExpr
- Data.Aeson.JSONPath.Query.Types: newtype LogicalOrExpr
- Data.Aeson.JSONPath.Query.Types: type TestExpr = Query
+ Data.Aeson.JSONPath.Query: qQuery :: Query -> QueryState -> Vector Value
+ Data.Aeson.JSONPath.Query: qQueryLocated :: Query -> QueryState -> String -> Vector (String, Value)
+ Data.Aeson.JSONPath.Types: ArraySlice :: (Maybe Int, Maybe Int, Int) -> Selector a
+ Data.Aeson.JSONPath.Types: Bracketed :: [Selector a] -> Segment a
+ Data.Aeson.JSONPath.Types: Child :: SegmentType
+ Data.Aeson.JSONPath.Types: Comp :: Comparable -> ComparisonOp -> Comparable -> ComparisonExpr
+ Data.Aeson.JSONPath.Types: CompLit :: Literal -> Comparable
+ Data.Aeson.JSONPath.Types: CompSQ :: SingularQuery -> Comparable
+ Data.Aeson.JSONPath.Types: Comparison :: ComparisonExpr -> BasicExpr a
+ Data.Aeson.JSONPath.Types: Current :: QueryType
+ Data.Aeson.JSONPath.Types: CurrentSQ :: SingularQueryType
+ Data.Aeson.JSONPath.Types: Descendant :: SegmentType
+ Data.Aeson.JSONPath.Types: Dotted :: Text -> Segment a
+ Data.Aeson.JSONPath.Types: Equal :: ComparisonOp
+ Data.Aeson.JSONPath.Types: Filter :: LogicalOrExpr a -> Selector a
+ Data.Aeson.JSONPath.Types: FilterQuery :: a -> TestExpr a
+ Data.Aeson.JSONPath.Types: Greater :: ComparisonOp
+ Data.Aeson.JSONPath.Types: GreaterOrEqual :: ComparisonOp
+ Data.Aeson.JSONPath.Types: Index :: Int -> Selector a
+ Data.Aeson.JSONPath.Types: IndexSQSeg :: Int -> SingularQuerySegment
+ Data.Aeson.JSONPath.Types: Less :: ComparisonOp
+ Data.Aeson.JSONPath.Types: LessOrEqual :: ComparisonOp
+ Data.Aeson.JSONPath.Types: LitBool :: Bool -> Literal
+ Data.Aeson.JSONPath.Types: LitNull :: Literal
+ Data.Aeson.JSONPath.Types: LitNum :: Scientific -> Literal
+ Data.Aeson.JSONPath.Types: LitString :: Text -> Literal
+ Data.Aeson.JSONPath.Types: LogicalAnd :: [BasicExpr a] -> LogicalAndExpr a
+ Data.Aeson.JSONPath.Types: LogicalOr :: [LogicalAndExpr a] -> LogicalOrExpr a
+ Data.Aeson.JSONPath.Types: Name :: Text -> Selector a
+ Data.Aeson.JSONPath.Types: NameSQSeg :: Text -> SingularQuerySegment
+ Data.Aeson.JSONPath.Types: NotEqual :: ComparisonOp
+ Data.Aeson.JSONPath.Types: NotParen :: LogicalOrExpr a -> BasicExpr a
+ Data.Aeson.JSONPath.Types: NotTest :: TestExpr a -> BasicExpr a
+ Data.Aeson.JSONPath.Types: Paren :: LogicalOrExpr a -> BasicExpr a
+ Data.Aeson.JSONPath.Types: Query :: QueryType -> [QuerySegment Query] -> Query
+ Data.Aeson.JSONPath.Types: QuerySegment :: SegmentType -> Segment a -> QuerySegment a
+ Data.Aeson.JSONPath.Types: QueryState :: Value -> Value -> (Query -> QueryState -> Vector Value) -> QueryState
+ Data.Aeson.JSONPath.Types: Root :: QueryType
+ Data.Aeson.JSONPath.Types: RootSQ :: SingularQueryType
+ Data.Aeson.JSONPath.Types: SingularQuery :: SingularQueryType -> [SingularQuerySegment] -> SingularQuery
+ Data.Aeson.JSONPath.Types: Test :: TestExpr a -> BasicExpr a
+ Data.Aeson.JSONPath.Types: WildcardSegment :: Segment a
+ Data.Aeson.JSONPath.Types: WildcardSelector :: Selector a
+ Data.Aeson.JSONPath.Types: [curVal] :: QueryState -> Value
+ Data.Aeson.JSONPath.Types: [executeQuery] :: QueryState -> Query -> QueryState -> Vector Value
+ Data.Aeson.JSONPath.Types: [querySegments] :: Query -> [QuerySegment Query]
+ Data.Aeson.JSONPath.Types: [queryType] :: Query -> QueryType
+ Data.Aeson.JSONPath.Types: [rootVal] :: QueryState -> Value
+ Data.Aeson.JSONPath.Types: [segmentType] :: QuerySegment a -> SegmentType
+ Data.Aeson.JSONPath.Types: [segment] :: QuerySegment a -> Segment a
+ Data.Aeson.JSONPath.Types: [singularQuerySegments] :: SingularQuery -> [SingularQuerySegment]
+ Data.Aeson.JSONPath.Types: [singularQueryType] :: SingularQuery -> SingularQueryType
+ Data.Aeson.JSONPath.Types: data BasicExpr a
+ Data.Aeson.JSONPath.Types: data Comparable
+ Data.Aeson.JSONPath.Types: data ComparisonExpr
+ Data.Aeson.JSONPath.Types: data ComparisonOp
+ Data.Aeson.JSONPath.Types: data Literal
+ Data.Aeson.JSONPath.Types: data Query
+ Data.Aeson.JSONPath.Types: data QuerySegment a
+ Data.Aeson.JSONPath.Types: data QueryState
+ Data.Aeson.JSONPath.Types: data QueryType
+ Data.Aeson.JSONPath.Types: data Segment a
+ Data.Aeson.JSONPath.Types: data SegmentType
+ Data.Aeson.JSONPath.Types: data Selector a
+ Data.Aeson.JSONPath.Types: data SingularQuery
+ Data.Aeson.JSONPath.Types: data SingularQuerySegment
+ Data.Aeson.JSONPath.Types: data SingularQueryType
+ Data.Aeson.JSONPath.Types: newtype LogicalAndExpr a
+ Data.Aeson.JSONPath.Types: newtype LogicalOrExpr a
+ Data.Aeson.JSONPath.Types: newtype TestExpr a
Files
- CHANGELOG.md +6/−0
- README.md +6/−5
- aeson-jsonpath.cabal +35/−5
- jsonpath-compliance-test-suite/cts.json +12702/−0
- src/Data/Aeson/JSONPath.hs +18/−9
- src/Data/Aeson/JSONPath/Parser.hs +5/−354
- src/Data/Aeson/JSONPath/Parser/Common.hs +21/−0
- src/Data/Aeson/JSONPath/Parser/Filter.hs +150/−0
- src/Data/Aeson/JSONPath/Parser/Name.hs +97/−0
- src/Data/Aeson/JSONPath/Parser/Number.hs +57/−0
- src/Data/Aeson/JSONPath/Parser/Query.hs +105/−0
- src/Data/Aeson/JSONPath/Query.hs +6/−278
- src/Data/Aeson/JSONPath/Query/Filter.hs +90/−0
- src/Data/Aeson/JSONPath/Query/Query.hs +35/−0
- src/Data/Aeson/JSONPath/Query/Segment.hs +92/−0
- src/Data/Aeson/JSONPath/Query/Selector.hs +139/−0
- src/Data/Aeson/JSONPath/Query/Types.hs +0/−139
- src/Data/Aeson/JSONPath/Types.hs +30/−0
- src/Data/Aeson/JSONPath/Types/Filter.hs +91/−0
- src/Data/Aeson/JSONPath/Types/Query.hs +34/−0
- src/Data/Aeson/JSONPath/Types/Segment.hs +32/−0
- src/Data/Aeson/JSONPath/Types/Selector.hs +19/−0
- test/ComplianceSpec.hs +0/−85
- test/LocatedSpec.hs +0/−143
- test/Main.hs +0/−45
- test/ParserSpec.hs +0/−442
- test/QuerySpec.hs +0/−342
- test/compliance/ComplianceSpec.hs +93/−0
- test/compliance/Main.hs +39/−0
- test/cts.json +0/−10941
- test/spec/LocatedSpec.hs +144/−0
- test/spec/Main.hs +29/−0
- test/spec/ParserSpec.hs +443/−0
- test/spec/QuerySpec.hs +348/−0
CHANGELOG.md view
@@ -2,6 +2,12 @@ All notable changes to this package are documented in this file. This project adheres to [Haskell PVP](https://pvp.haskell.org/) versioning. +## 0.3.0.2++- #43, Fix spaces not allowed in relative query and singular query segments+- #50, Fix wrong normalized path with descendant segment+- #30, Fix escape characters not handled properly in normalized path+ ## 0.3.0.1 - #31, Fix `test/cts.json` not included in hackage bundle
README.md view
@@ -1,6 +1,6 @@ # aeson-jsonpath - [](https://hackage.haskell.org/package/aeson-jsonpath) [](https://www.patreon.com/taimoorzaeem) +[](https://github.com/taimoorzaeem/aeson-jsonpath/actions/workflows/build.yml) [](https://hackage.haskell.org/package/aeson-jsonpath) [](https://www.patreon.com/taimoorzaeem) [](https://github.com/taimoorzaeem/aeson-jsonpath/actions/workflows/compliance.yml) Run [RFC 9535](https://www.rfc-editor.org/rfc/rfc9535) compliant JSONPath queries on [Data.Aeson](https://hackage.haskell.org/package/aeson). @@ -15,10 +15,11 @@ - [x] Segments - [x] Child Segment - [x] Descendant Segment-- [x] Node Locations (Normalized Path)+- [x] Normalized Paths - [ ] Function Extensions-- [ ] Setting Values (Non-RFC) +I have decided not to implement Function Extension yet. Please open an issue or discussion if you'd like to see them implemented.+ ## Quick Start ```haskell@@ -56,7 +57,7 @@ "year": 2018 }, {- "title": "Lawrence Anyways",+ "title": "Laurence Anyways", "director": "Xavier Dolan", "year": 2012 }@@ -111,7 +112,7 @@ Right [ Object (fromList [ ("director",String "Xavier Dolan"),- ("title",String "Lawrence Anyways"),+ ("title",String "Laurence Anyways"), ("year",Number 2012.0) ]) ]
aeson-jsonpath.cabal view
@@ -1,5 +1,5 @@ name: aeson-jsonpath-version: 0.3.0.1+version: 0.3.0.2 synopsis: Parse and run JSONPath queries on Aeson documents description: RFC 9535 compliant JSONPath parsing and querying package. JSONPath is similar to XPath for querying@@ -14,7 +14,7 @@ build-type: Simple extra-source-files: CHANGELOG.md extra-doc-files: README.md-data-files: test/cts.json+data-files: jsonpath-compliance-test-suite/cts.json cabal-version: 1.18 tested-with:@@ -36,7 +36,20 @@ exposed-modules: Data.Aeson.JSONPath Data.Aeson.JSONPath.Parser Data.Aeson.JSONPath.Query- Data.Aeson.JSONPath.Query.Types+ Data.Aeson.JSONPath.Types+ other-modules: Data.Aeson.JSONPath.Parser.Query+ Data.Aeson.JSONPath.Parser.Filter+ Data.Aeson.JSONPath.Parser.Name+ Data.Aeson.JSONPath.Parser.Number+ Data.Aeson.JSONPath.Parser.Common+ Data.Aeson.JSONPath.Query.Query+ Data.Aeson.JSONPath.Query.Segment+ Data.Aeson.JSONPath.Query.Selector+ Data.Aeson.JSONPath.Query.Filter+ Data.Aeson.JSONPath.Types.Query+ Data.Aeson.JSONPath.Types.Segment+ Data.Aeson.JSONPath.Types.Selector+ Data.Aeson.JSONPath.Types.Filter build-depends: aeson >= 2.0.3 && < 2.3 , base >= 4.9 && < 4.22 , parsec >= 3.1.11 && < 3.2@@ -53,12 +66,29 @@ default-extensions: OverloadedStrings NoImplicitPrelude QuasiQuotes- hs-source-dirs: test+ hs-source-dirs: test/spec main-is: Main.hs other-modules: ParserSpec QuerySpec- ComplianceSpec LocatedSpec+ build-depends: aeson >= 2.0.3 && < 2.3+ , aeson-jsonpath+ , base >= 4.9 && < 4.22+ , hspec >= 2.3 && < 2.12+ , parsec >= 3.1.11 && < 3.2+ , vector >= 0.11 && < 0.14++ ghc-options: -Wall -Wunused-packages++test-suite compliance+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ default-extensions: OverloadedStrings+ NoImplicitPrelude+ QuasiQuotes+ hs-source-dirs: test/compliance+ main-is: Main.hs+ other-modules: ComplianceSpec Paths_aeson_jsonpath build-depends: aeson >= 2.0.3 && < 2.3 , aeson-jsonpath
+ jsonpath-compliance-test-suite/cts.json view
@@ -0,0 +1,12702 @@+{+ "description": "JSONPath Compliance Test Suite. This file is autogenerated, do not edit.",+ "tests": [+ {+ "name": "basic, root",+ "selector": "$",+ "document": [+ "first",+ "second"+ ],+ "result": [+ [+ "first",+ "second"+ ]+ ],+ "result_paths": [+ "$"+ ]+ },+ {+ "name": "basic, no leading whitespace",+ "selector": " $",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "basic, no trailing whitespace",+ "selector": "$ ",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "basic, name shorthand",+ "selector": "$.a",+ "document": {+ "a": "A",+ "b": "B"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['a']"+ ]+ },+ {+ "name": "basic, name shorthand, extended unicode ☺",+ "selector": "$.☺",+ "document": {+ "☺": "A",+ "b": "B"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['☺']"+ ]+ },+ {+ "name": "basic, name shorthand, underscore",+ "selector": "$._",+ "document": {+ "_": "A",+ "_foo": "B"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['_']"+ ]+ },+ {+ "name": "basic, name shorthand, symbol",+ "selector": "$.&",+ "invalid_selector": true+ },+ {+ "name": "basic, name shorthand, number",+ "selector": "$.1",+ "invalid_selector": true+ },+ {+ "name": "basic, name shorthand, absent data",+ "selector": "$.c",+ "document": {+ "a": "A",+ "b": "B"+ },+ "result": [],+ "result_paths": []+ },+ {+ "name": "basic, name shorthand, array data",+ "selector": "$.a",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "basic, name shorthand, object data, nested",+ "selector": "$.a.b.c",+ "document": {+ "a": {+ "b": {+ "c": "C"+ }+ }+ },+ "result": [+ "C"+ ],+ "result_paths": [+ "$['a']['b']['c']"+ ]+ },+ {+ "name": "basic, wildcard shorthand, object data",+ "selector": "$.*",+ "document": {+ "a": "A",+ "b": "B"+ },+ "results": [+ [+ "A",+ "B"+ ],+ [+ "B",+ "A"+ ]+ ],+ "results_paths": [+ [+ "$['a']",+ "$['b']"+ ],+ [+ "$['b']",+ "$['a']"+ ]+ ]+ },+ {+ "name": "basic, wildcard shorthand, array data",+ "selector": "$.*",+ "document": [+ "first",+ "second"+ ],+ "result": [+ "first",+ "second"+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "basic, wildcard selector, array data",+ "selector": "$[*]",+ "document": [+ "first",+ "second"+ ],+ "result": [+ "first",+ "second"+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "basic, wildcard shorthand, then name shorthand",+ "selector": "$.*.a",+ "document": {+ "x": {+ "a": "Ax",+ "b": "Bx"+ },+ "y": {+ "a": "Ay",+ "b": "By"+ }+ },+ "results": [+ [+ "Ax",+ "Ay"+ ],+ [+ "Ay",+ "Ax"+ ]+ ],+ "results_paths": [+ [+ "$['x']['a']",+ "$['y']['a']"+ ],+ [+ "$['y']['a']",+ "$['x']['a']"+ ]+ ]+ },+ {+ "name": "basic, multiple selectors",+ "selector": "$[0,2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0,+ 2+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ]+ },+ {+ "name": "basic, multiple selectors, space instead of comma",+ "selector": "$[0 2]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "basic, selector, leading comma",+ "selector": "$[,0]",+ "invalid_selector": true+ },+ {+ "name": "basic, selector, trailing comma",+ "selector": "$[0,]",+ "invalid_selector": true+ },+ {+ "name": "basic, multiple selectors, name and index, array data",+ "selector": "$['a',1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "basic, multiple selectors, name and index, object data",+ "selector": "$['a',1]",+ "document": {+ "a": 1,+ "b": 2+ },+ "result": [+ 1+ ],+ "result_paths": [+ "$['a']"+ ]+ },+ {+ "name": "basic, multiple selectors, index and slice",+ "selector": "$[1,5:7]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1,+ 5,+ 6+ ],+ "result_paths": [+ "$[1]",+ "$[5]",+ "$[6]"+ ]+ },+ {+ "name": "basic, multiple selectors, index and slice, overlapping",+ "selector": "$[1,0:3]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1,+ 0,+ 1,+ 2+ ],+ "result_paths": [+ "$[1]",+ "$[0]",+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "basic, multiple selectors, duplicate index",+ "selector": "$[1,1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1,+ 1+ ],+ "result_paths": [+ "$[1]",+ "$[1]"+ ]+ },+ {+ "name": "basic, multiple selectors, wildcard and index",+ "selector": "$[*,1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9,+ 1+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]",+ "$[4]",+ "$[5]",+ "$[6]",+ "$[7]",+ "$[8]",+ "$[9]",+ "$[1]"+ ]+ },+ {+ "name": "basic, multiple selectors, wildcard and name",+ "selector": "$[*,'a']",+ "document": {+ "a": "A",+ "b": "B"+ },+ "results": [+ [+ "A",+ "B",+ "A"+ ],+ [+ "B",+ "A",+ "A"+ ]+ ],+ "results_paths": [+ [+ "$['a']",+ "$['b']",+ "$['a']"+ ],+ [+ "$['b']",+ "$['a']",+ "$['a']"+ ]+ ]+ },+ {+ "name": "basic, multiple selectors, wildcard and slice",+ "selector": "$[*,0:2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9,+ 0,+ 1+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]",+ "$[4]",+ "$[5]",+ "$[6]",+ "$[7]",+ "$[8]",+ "$[9]",+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "basic, multiple selectors, multiple wildcards",+ "selector": "$[*,*]",+ "document": [+ 0,+ 1,+ 2+ ],+ "result": [+ 0,+ 1,+ 2,+ 0,+ 1,+ 2+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[0]",+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "basic, empty segment",+ "selector": "$[]",+ "invalid_selector": true+ },+ {+ "name": "basic, descendant segment, index",+ "selector": "$..[1]",+ "document": {+ "o": [+ 0,+ 1,+ [+ 2,+ 3+ ]+ ]+ },+ "result": [+ 1,+ 3+ ],+ "result_paths": [+ "$['o'][1]",+ "$['o'][2][1]"+ ]+ },+ {+ "name": "basic, descendant segment, name shorthand",+ "selector": "$..a",+ "document": {+ "o": [+ {+ "a": "b"+ },+ {+ "a": "c"+ }+ ]+ },+ "result": [+ "b",+ "c"+ ],+ "result_paths": [+ "$['o'][0]['a']",+ "$['o'][1]['a']"+ ]+ },+ {+ "name": "basic, descendant segment, wildcard shorthand, array data",+ "selector": "$..*",+ "document": [+ 0,+ 1+ ],+ "result": [+ 0,+ 1+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "basic, descendant segment, wildcard selector, array data",+ "selector": "$..[*]",+ "document": [+ 0,+ 1+ ],+ "result": [+ 0,+ 1+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "basic, descendant segment, wildcard selector, nested arrays",+ "selector": "$..[*]",+ "document": [+ [+ [+ 1+ ]+ ],+ [+ 2+ ]+ ],+ "results": [+ [+ [+ [+ 1+ ]+ ],+ [+ 2+ ],+ [+ 1+ ],+ 1,+ 2+ ],+ [+ [+ [+ 1+ ]+ ],+ [+ 2+ ],+ [+ 1+ ],+ 2,+ 1+ ]+ ],+ "results_paths": [+ [+ "$[0]",+ "$[1]",+ "$[0][0]",+ "$[0][0][0]",+ "$[1][0]"+ ],+ [+ "$[0]",+ "$[1]",+ "$[0][0]",+ "$[1][0]",+ "$[0][0][0]"+ ]+ ]+ },+ {+ "name": "basic, descendant segment, wildcard selector, nested objects",+ "selector": "$..[*]",+ "document": {+ "a": {+ "c": {+ "e": 1+ }+ },+ "b": {+ "d": 2+ }+ },+ "results": [+ [+ {+ "c": {+ "e": 1+ }+ },+ {+ "d": 2+ },+ {+ "e": 1+ },+ 1,+ 2+ ],+ [+ {+ "c": {+ "e": 1+ }+ },+ {+ "d": 2+ },+ {+ "e": 1+ },+ 2,+ 1+ ],+ [+ {+ "c": {+ "e": 1+ }+ },+ {+ "d": 2+ },+ 2,+ {+ "e": 1+ },+ 1+ ],+ [+ {+ "d": 2+ },+ {+ "c": {+ "e": 1+ }+ },+ {+ "e": 1+ },+ 1,+ 2+ ],+ [+ {+ "d": 2+ },+ {+ "c": {+ "e": 1+ }+ },+ {+ "e": 1+ },+ 2,+ 1+ ],+ [+ {+ "d": 2+ },+ {+ "c": {+ "e": 1+ }+ },+ 2,+ {+ "e": 1+ },+ 1+ ]+ ],+ "results_paths": [+ [+ "$['a']",+ "$['b']",+ "$['a']['c']",+ "$['a']['c']['e']",+ "$['b']['d']"+ ],+ [+ "$['a']",+ "$['b']",+ "$['a']['c']",+ "$['b']['d']",+ "$['a']['c']['e']"+ ],+ [+ "$['a']",+ "$['b']",+ "$['b']['d']",+ "$['a']['c']",+ "$['a']['c']['e']"+ ],+ [+ "$['b']",+ "$['a']",+ "$['a']['c']",+ "$['a']['c']['e']",+ "$['b']['d']"+ ],+ [+ "$['b']",+ "$['a']",+ "$['a']['c']",+ "$['b']['d']",+ "$['a']['c']['e']"+ ],+ [+ "$['b']",+ "$['a']",+ "$['b']['d']",+ "$['a']['c']",+ "$['a']['c']['e']"+ ]+ ]+ },+ {+ "name": "basic, descendant segment, wildcard shorthand, object data",+ "selector": "$..*",+ "document": {+ "a": "b"+ },+ "result": [+ "b"+ ],+ "result_paths": [+ "$['a']"+ ]+ },+ {+ "name": "basic, descendant segment, wildcard shorthand, nested data",+ "selector": "$..*",+ "document": {+ "o": [+ {+ "a": "b"+ }+ ]+ },+ "result": [+ [+ {+ "a": "b"+ }+ ],+ {+ "a": "b"+ },+ "b"+ ],+ "result_paths": [+ "$['o']",+ "$['o'][0]",+ "$['o'][0]['a']"+ ]+ },+ {+ "name": "basic, descendant segment, multiple selectors",+ "selector": "$..['a','d']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ "b",+ "e",+ "c",+ "f"+ ],+ "result_paths": [+ "$[0]['a']",+ "$[0]['d']",+ "$[1]['a']",+ "$[1]['d']"+ ]+ },+ {+ "name": "basic, descendant segment, object traversal, multiple selectors",+ "selector": "$..['a','d']",+ "document": {+ "x": {+ "a": "b",+ "d": "e"+ },+ "y": {+ "a": "c",+ "d": "f"+ }+ },+ "results": [+ [+ "b",+ "e",+ "c",+ "f"+ ],+ [+ "c",+ "f",+ "b",+ "e"+ ]+ ],+ "results_paths": [+ [+ "$['x']['a']",+ "$['x']['d']",+ "$['y']['a']",+ "$['y']['d']"+ ],+ [+ "$['y']['a']",+ "$['y']['d']",+ "$['x']['a']",+ "$['x']['d']"+ ]+ ]+ },+ {+ "name": "basic, bald descendant segment",+ "selector": "$..",+ "invalid_selector": true+ },+ {+ "name": "basic, current node identifier without filter selector",+ "selector": "$[@.a]",+ "invalid_selector": true+ },+ {+ "name": "basic, root node identifier in brackets without filter selector",+ "selector": "$[$.a]",+ "invalid_selector": true+ },+ {+ "name": "filter, existence, without segments",+ "selector": "$[?@]",+ "document": {+ "a": 1,+ "b": null+ },+ "results": [+ [+ 1,+ null+ ],+ [+ null,+ 1+ ]+ ],+ "results_paths": [+ [+ "$['a']",+ "$['b']"+ ],+ [+ "$['b']",+ "$['a']"+ ]+ ]+ },+ {+ "name": "filter, existence",+ "selector": "$[?@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, existence, present with null",+ "selector": "$[?@.a]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": null,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, absolute existence, without segments",+ "selector": "$[?$]",+ "document": {+ "a": 1,+ "b": null+ },+ "results": [+ [+ 1,+ null+ ],+ [+ null,+ 1+ ]+ ],+ "results_paths": [+ [+ "$['a']",+ "$['b']"+ ],+ [+ "$['b']",+ "$['a']"+ ]+ ]+ },+ {+ "name": "filter, absolute existence, with segments",+ "selector": "$[?$.*.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, equals string, single quotes",+ "selector": "$[?@.a=='b']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals numeric string, single quotes",+ "selector": "$[?@.a=='1']",+ "document": [+ {+ "a": "1",+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "1",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals string, double quotes",+ "selector": "$[?@.a==\"b\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals numeric string, double quotes",+ "selector": "$[?@.a==\"1\"]",+ "document": [+ {+ "a": "1",+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "1",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number",+ "selector": "$[?@.a==1]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals null",+ "selector": "$[?@.a==null]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": null,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals null, absent from data",+ "selector": "$[?@.a==null]",+ "document": [+ {+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, equals true",+ "selector": "$[?@.a==true]",+ "document": [+ {+ "a": true,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": true,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals false",+ "selector": "$[?@.a==false]",+ "document": [+ {+ "a": false,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": false,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals self",+ "selector": "$[?@==@]",+ "document": [+ 1,+ null,+ true,+ {+ "a": "b"+ },+ [+ false+ ]+ ],+ "result": [+ 1,+ null,+ true,+ {+ "a": "b"+ },+ [+ false+ ]+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]",+ "$[4]"+ ]+ },+ {+ "name": "filter, absolute, equals self",+ "selector": "$[?$==$]",+ "document": [+ 1,+ null,+ true,+ {+ "a": "b"+ },+ [+ false+ ]+ ],+ "result": [+ 1,+ null,+ true,+ {+ "a": "b"+ },+ [+ false+ ]+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]",+ "$[4]"+ ]+ },+ {+ "name": "filter, equals, absent from index selector equals absent from name selector",+ "selector": "$[?@.absent==@.list[9]]",+ "document": [+ {+ "list": [+ 1+ ]+ }+ ],+ "result": [+ {+ "list": [+ 1+ ]+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, deep equality, arrays",+ "selector": "$[?@.a==@.b]",+ "document": [+ {+ "a": false,+ "b": [+ 1,+ 2+ ]+ },+ {+ "a": [+ [+ 1,+ [+ 2+ ]+ ]+ ],+ "b": [+ [+ 1,+ [+ 2+ ]+ ]+ ]+ },+ {+ "a": [+ [+ 1,+ [+ 2+ ]+ ]+ ],+ "b": [+ [+ [+ 2+ ],+ 1+ ]+ ]+ },+ {+ "a": [+ [+ 1,+ [+ 2+ ]+ ]+ ],+ "b": [+ [+ 1,+ 2+ ]+ ]+ }+ ],+ "result": [+ {+ "a": [+ [+ 1,+ [+ 2+ ]+ ]+ ],+ "b": [+ [+ 1,+ [+ 2+ ]+ ]+ ]+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, deep equality, objects",+ "selector": "$[?@.a==@.b]",+ "document": [+ {+ "a": false,+ "b": {+ "x": 1,+ "y": {+ "z": 1+ }+ }+ },+ {+ "a": {+ "x": 1,+ "y": {+ "z": 1+ }+ },+ "b": {+ "x": 1,+ "y": {+ "z": 1+ }+ }+ },+ {+ "a": {+ "x": 1,+ "y": {+ "z": 1+ }+ },+ "b": {+ "y": {+ "z": 1+ },+ "x": 1+ }+ },+ {+ "a": {+ "x": 1,+ "y": {+ "z": 1+ }+ },+ "b": {+ "x": 1+ }+ },+ {+ "a": {+ "x": 1,+ "y": {+ "z": 1+ }+ },+ "b": {+ "x": 1,+ "y": {+ "z": 2+ }+ }+ }+ ],+ "result": [+ {+ "a": {+ "x": 1,+ "y": {+ "z": 1+ }+ },+ "b": {+ "x": 1,+ "y": {+ "z": 1+ }+ }+ },+ {+ "a": {+ "x": 1,+ "y": {+ "z": 1+ }+ },+ "b": {+ "y": {+ "z": 1+ },+ "x": 1+ }+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "filter, not-equals string, single quotes",+ "selector": "$[?@.a!='b']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals numeric string, single quotes",+ "selector": "$[?@.a!='1']",+ "document": [+ {+ "a": "1",+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals string, single quotes, different type",+ "selector": "$[?@.a!='b']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals string, double quotes",+ "selector": "$[?@.a!=\"b\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals numeric string, double quotes",+ "selector": "$[?@.a!=\"1\"]",+ "document": [+ {+ "a": "1",+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals string, double quotes, different types",+ "selector": "$[?@.a!=\"b\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals number",+ "selector": "$[?@.a!=1]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "filter, not-equals number, different types",+ "selector": "$[?@.a!=1]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals null",+ "selector": "$[?@.a!=null]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals null, absent from data",+ "selector": "$[?@.a!=null]",+ "document": [+ {+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals true",+ "selector": "$[?@.a!=true]",+ "document": [+ {+ "a": true,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not-equals false",+ "selector": "$[?@.a!=false]",+ "document": [+ {+ "a": false,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, less than string, single quotes",+ "selector": "$[?@.a<'c']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, less than string, double quotes",+ "selector": "$[?@.a<\"c\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, less than number",+ "selector": "$[?@.a<10]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 10,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, less than null",+ "selector": "$[?@.a<null]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, less than true",+ "selector": "$[?@.a<true]",+ "document": [+ {+ "a": true,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, less than false",+ "selector": "$[?@.a<false]",+ "document": [+ {+ "a": false,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, less than or equal to string, single quotes",+ "selector": "$[?@.a<='c']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, less than or equal to string, double quotes",+ "selector": "$[?@.a<=\"c\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, less than or equal to number",+ "selector": "$[?@.a<=10]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 10,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 10,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, less than or equal to null",+ "selector": "$[?@.a<=null]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": null,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, less than or equal to true",+ "selector": "$[?@.a<=true]",+ "document": [+ {+ "a": true,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": true,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, less than or equal to false",+ "selector": "$[?@.a<=false]",+ "document": [+ {+ "a": false,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": false,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, greater than string, single quotes",+ "selector": "$[?@.a>'c']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[2]"+ ]+ },+ {+ "name": "filter, greater than string, double quotes",+ "selector": "$[?@.a>\"c\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[2]"+ ]+ },+ {+ "name": "filter, greater than number",+ "selector": "$[?@.a>10]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 10,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[3]"+ ]+ },+ {+ "name": "filter, greater than null",+ "selector": "$[?@.a>null]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, greater than true",+ "selector": "$[?@.a>true]",+ "document": [+ {+ "a": true,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, greater than false",+ "selector": "$[?@.a>false]",+ "document": [+ {+ "a": false,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, greater than or equal to string, single quotes",+ "selector": "$[?@.a>='c']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "filter, greater than or equal to string, double quotes",+ "selector": "$[?@.a>=\"c\"]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "filter, greater than or equal to number",+ "selector": "$[?@.a>=10]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 10,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 10,+ "d": "e"+ },+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ]+ },+ {+ "name": "filter, greater than or equal to null",+ "selector": "$[?@.a>=null]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": null,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, greater than or equal to true",+ "selector": "$[?@.a>=true]",+ "document": [+ {+ "a": true,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": true,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, greater than or equal to false",+ "selector": "$[?@.a>=false]",+ "document": [+ {+ "a": false,+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": false,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, exists and not-equals null, absent from data",+ "selector": "$[?@.a&&@.a!=null]",+ "document": [+ {+ "d": "e"+ },+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, exists and exists, data false",+ "selector": "$[?@.a&&@.b]",+ "document": [+ {+ "a": false,+ "b": false+ },+ {+ "b": false+ },+ {+ "c": false+ }+ ],+ "result": [+ {+ "a": false,+ "b": false+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, exists or exists, data false",+ "selector": "$[?@.a||@.b]",+ "document": [+ {+ "a": false,+ "b": false+ },+ {+ "b": false+ },+ {+ "c": false+ }+ ],+ "result": [+ {+ "a": false,+ "b": false+ },+ {+ "b": false+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, and",+ "selector": "$[?@.a>0&&@.a<10]",+ "document": [+ {+ "a": -10,+ "d": "e"+ },+ {+ "a": 5,+ "d": "f"+ },+ {+ "a": 20,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": 5,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, or",+ "selector": "$[?@.a=='b'||@.a=='d']",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "c",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ]+ },+ {+ "name": "filter, not expression",+ "selector": "$[?!(@.a=='b')]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ]+ },+ {+ "name": "filter, not exists",+ "selector": "$[?!@.a]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, not exists, data null",+ "selector": "$[?!@.a]",+ "document": [+ {+ "a": null,+ "d": "e"+ },+ {+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ]+ },+ {+ "name": "filter, non-singular existence, wildcard",+ "selector": "$[?@.*]",+ "document": [+ 1,+ [],+ [+ 2+ ],+ {},+ {+ "a": 3+ }+ ],+ "result": [+ [+ 2+ ],+ {+ "a": 3+ }+ ],+ "result_paths": [+ "$[2]",+ "$[4]"+ ]+ },+ {+ "name": "filter, non-singular existence, multiple",+ "selector": "$[?@[0, 0, 'a']]",+ "document": [+ 1,+ [],+ [+ 2+ ],+ [+ 2,+ 3+ ],+ {+ "a": 3+ },+ {+ "b": 4+ },+ {+ "a": 3,+ "b": 4+ }+ ],+ "result": [+ [+ 2+ ],+ [+ 2,+ 3+ ],+ {+ "a": 3+ },+ {+ "a": 3,+ "b": 4+ }+ ],+ "result_paths": [+ "$[2]",+ "$[3]",+ "$[4]",+ "$[6]"+ ]+ },+ {+ "name": "filter, non-singular existence, slice",+ "selector": "$[?@[0:2]]",+ "document": [+ 1,+ [],+ [+ 2+ ],+ [+ 2,+ 3,+ 4+ ],+ {},+ {+ "a": 3+ }+ ],+ "result": [+ [+ 2+ ],+ [+ 2,+ 3,+ 4+ ]+ ],+ "result_paths": [+ "$[2]",+ "$[3]"+ ]+ },+ {+ "name": "filter, non-singular existence, negated",+ "selector": "$[?!@.*]",+ "document": [+ 1,+ [],+ [+ 2+ ],+ {},+ {+ "a": 3+ }+ ],+ "result": [+ 1,+ [],+ {}+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[3]"+ ]+ },+ {+ "name": "filter, non-singular query in comparison, slice",+ "selector": "$[?@[0:0]==0]",+ "invalid_selector": true+ },+ {+ "name": "filter, non-singular query in comparison, all children",+ "selector": "$[?@[*]==0]",+ "invalid_selector": true+ },+ {+ "name": "filter, non-singular query in comparison, descendants",+ "selector": "$[?@..a==0]",+ "invalid_selector": true+ },+ {+ "name": "filter, non-singular query in comparison, combined",+ "selector": "$[?@.a[*].a==0]",+ "invalid_selector": true+ },+ {+ "name": "filter, nested",+ "selector": "$[?@[?@>1]]",+ "document": [+ [+ 0+ ],+ [+ 0,+ 1+ ],+ [+ 0,+ 1,+ 2+ ],+ [+ 42+ ]+ ],+ "result": [+ [+ 0,+ 1,+ 2+ ],+ [+ 42+ ]+ ],+ "result_paths": [+ "$[2]",+ "$[3]"+ ]+ },+ {+ "name": "filter, name segment on primitive, selects nothing",+ "selector": "$[?@.a == 1]",+ "document": {+ "a": 1+ },+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, name segment on array, selects nothing",+ "selector": "$[?@['0'] == 5]",+ "document": [+ [+ 5,+ 6+ ]+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, index segment on object, selects nothing",+ "selector": "$[?@[0] == 5]",+ "document": [+ {+ "0": 5+ }+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "filter, followed by name selector",+ "selector": "$[?@.a==1].b.x",+ "document": [+ {+ "a": 1,+ "b": {+ "x": 2+ }+ }+ ],+ "result": [+ 2+ ],+ "result_paths": [+ "$[0]['b']['x']"+ ]+ },+ {+ "name": "filter, followed by child segment that selects multiple elements",+ "selector": "$[?@.z=='_']['x','y']",+ "document": [+ {+ "x": 1,+ "y": null,+ "z": "_"+ }+ ],+ "result": [+ 1,+ null+ ],+ "result_paths": [+ "$[0]['x']",+ "$[0]['y']"+ ]+ },+ {+ "name": "filter, relative non-singular query, index, equal",+ "selector": "$[?(@[0, 0]==42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, index, not equal",+ "selector": "$[?(@[0, 0]!=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, index, less-or-equal",+ "selector": "$[?(@[0, 0]<=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, name, equal",+ "selector": "$[?(@['a', 'a']==42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, name, not equal",+ "selector": "$[?(@['a', 'a']!=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, name, less-or-equal",+ "selector": "$[?(@['a', 'a']<=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, combined, equal",+ "selector": "$[?(@[0, '0']==42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, combined, not equal",+ "selector": "$[?(@[0, '0']!=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, combined, less-or-equal",+ "selector": "$[?(@[0, '0']<=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, relative non-singular query, wildcard, equal",+ "selector": "$[?(@.*==42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, relative non-singular query, wildcard, not equal",+ "selector": "$[?(@.*!=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, relative non-singular query, wildcard, less-or-equal",+ "selector": "$[?(@.*<=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, relative non-singular query, slice, equal",+ "selector": "$[?(@[0:0]==42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, relative non-singular query, slice, not equal",+ "selector": "$[?(@[0:0]!=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, relative non-singular query, slice, less-or-equal",+ "selector": "$[?(@[0:0]<=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, absolute non-singular query, index, equal",+ "selector": "$[?($[0, 0]==42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, index, not equal",+ "selector": "$[?($[0, 0]!=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, index, less-or-equal",+ "selector": "$[?($[0, 0]<=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, name, equal",+ "selector": "$[?($['a', 'a']==42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, name, not equal",+ "selector": "$[?($['a', 'a']!=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, name, less-or-equal",+ "selector": "$[?($['a', 'a']<=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, combined, equal",+ "selector": "$[?($[0, '0']==42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, combined, not equal",+ "selector": "$[?($[0, '0']!=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, combined, less-or-equal",+ "selector": "$[?($[0, '0']<=42)]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, absolute non-singular query, wildcard, equal",+ "selector": "$[?($.*==42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, absolute non-singular query, wildcard, not equal",+ "selector": "$[?($.*!=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, absolute non-singular query, wildcard, less-or-equal",+ "selector": "$[?($.*<=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, absolute non-singular query, slice, equal",+ "selector": "$[?($[0:0]==42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, absolute non-singular query, slice, not equal",+ "selector": "$[?($[0:0]!=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, absolute non-singular query, slice, less-or-equal",+ "selector": "$[?($[0:0]<=42)]",+ "invalid_selector": true+ },+ {+ "name": "filter, multiple selectors",+ "selector": "$[?@.a,?@.b]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, multiple selectors, comparison",+ "selector": "$[?@.a=='b',?@.b=='x']",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, multiple selectors, overlapping",+ "selector": "$[?@.a,?@.d]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, multiple selectors, filter and index",+ "selector": "$[?@.a,1]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, multiple selectors, filter and wildcard",+ "selector": "$[?@.a,*]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[0]",+ "$[1]"+ ]+ },+ {+ "name": "filter, multiple selectors, filter and slice",+ "selector": "$[?@.a,1:]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ },+ {+ "g": "h"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ },+ {+ "g": "h"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]"+ ]+ },+ {+ "name": "filter, multiple selectors, comparison filter, index and slice",+ "selector": "$[1, ?@.a=='b', 1:]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "b": "c",+ "d": "f"+ },+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, equals number, zero and negative zero",+ "selector": "$[?@.a==0]",+ "document": [+ {+ "a": 0,+ "d": "e"+ },+ {+ "a": 0.1,+ "d": "f"+ },+ {+ "a": "0",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 0,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, negative zero and zero",+ "selector": "$[?@.a==-0]",+ "document": [+ {+ "a": 0,+ "d": "e"+ },+ {+ "a": 0.1,+ "d": "f"+ },+ {+ "a": "0",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 0,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, with and without decimal fraction",+ "selector": "$[?@.a==1.0]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent",+ "selector": "$[?@.a==1e2]",+ "document": [+ {+ "a": 100,+ "d": "e"+ },+ {+ "a": 100.1,+ "d": "f"+ },+ {+ "a": "100",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 100,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent upper e",+ "selector": "$[?@.a==1E2]",+ "document": [+ {+ "a": 100,+ "d": "e"+ },+ {+ "a": 100.1,+ "d": "f"+ },+ {+ "a": "100",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 100,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, positive exponent",+ "selector": "$[?@.a==1e+2]",+ "document": [+ {+ "a": 100,+ "d": "e"+ },+ {+ "a": 100.1,+ "d": "f"+ },+ {+ "a": "100",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 100,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, negative exponent",+ "selector": "$[?@.a==1e-2]",+ "document": [+ {+ "a": 0.01,+ "d": "e"+ },+ {+ "a": 0.02,+ "d": "f"+ },+ {+ "a": "0.01",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 0.01,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent 0",+ "selector": "$[?@.a==1e0]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent -0",+ "selector": "$[?@.a==1e-0]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent +0",+ "selector": "$[?@.a==1e+0]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent leading -0",+ "selector": "$[?@.a==1e-02]",+ "document": [+ {+ "a": 0.01,+ "d": "e"+ },+ {+ "a": 0.02,+ "d": "f"+ },+ {+ "a": "0.01",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 0.01,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, exponent +00",+ "selector": "$[?@.a==1e+00]",+ "document": [+ {+ "a": 1,+ "d": "e"+ },+ {+ "a": 2,+ "d": "f"+ },+ {+ "a": "1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, decimal fraction",+ "selector": "$[?@.a==1.1]",+ "document": [+ {+ "a": 1.1,+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ },+ {+ "a": "1.1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1.1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, decimal fraction, trailing 0",+ "selector": "$[?@.a==1.10]",+ "document": [+ {+ "a": 1.1,+ "d": "e"+ },+ {+ "a": 1,+ "d": "f"+ },+ {+ "a": "1.1",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 1.1,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, decimal fraction, exponent",+ "selector": "$[?@.a==1.1e2]",+ "document": [+ {+ "a": 110,+ "d": "e"+ },+ {+ "a": 110.1,+ "d": "f"+ },+ {+ "a": "110",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 110,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, decimal fraction, positive exponent",+ "selector": "$[?@.a==1.1e+2]",+ "document": [+ {+ "a": 110,+ "d": "e"+ },+ {+ "a": 110.1,+ "d": "f"+ },+ {+ "a": "110",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 110,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, decimal fraction, negative exponent",+ "selector": "$[?@.a==1.1e-2]",+ "document": [+ {+ "a": 0.011,+ "d": "e"+ },+ {+ "a": 0.012,+ "d": "f"+ },+ {+ "a": "0.011",+ "d": "g"+ }+ ],+ "result": [+ {+ "a": 0.011,+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, equals number, invalid plus",+ "selector": "$[?@.a==+1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid minus space",+ "selector": "$[?@.a==- 1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid double minus",+ "selector": "$[?@.a==--1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid no int digit",+ "selector": "$[?@.a==.1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid minus no int digit",+ "selector": "$[?@.a==-.1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid 00",+ "selector": "$[?@.a==00]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid leading 0",+ "selector": "$[?@.a==01]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid no fractional digit",+ "selector": "$[?@.a==1.]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid middle minus",+ "selector": "$[?@.a==1.-1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid no fractional digit e",+ "selector": "$[?@.a==1.e1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid no e digit",+ "selector": "$[?@.a==1e]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid no e digit minus",+ "selector": "$[?@.a==1e-]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid double e",+ "selector": "$[?@.a==1eE1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid e digit double minus",+ "selector": "$[?@.a==1e--1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid e digit plus minus",+ "selector": "$[?@.a==1e+-1]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid e decimal",+ "selector": "$[?@.a==1e2.3]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals number, invalid multi e",+ "selector": "$[?@.a==1e2e3]",+ "invalid_selector": true+ },+ {+ "name": "filter, equals, special nothing",+ "selector": "$.values[?length(@.a) == value($..c)]",+ "document": {+ "c": "cd",+ "values": [+ {+ "a": "ab"+ },+ {+ "c": "d"+ },+ {+ "a": null+ }+ ]+ },+ "result": [+ {+ "c": "d"+ },+ {+ "a": null+ }+ ],+ "result_paths": [+ "$['values'][1]",+ "$['values'][2]"+ ],+ "tags": [+ "function"+ ]+ },+ {+ "name": "filter, equals, empty node list and empty node list",+ "selector": "$[?@.a == @.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "c": 3+ }+ ],+ "result_paths": [+ "$[2]"+ ]+ },+ {+ "name": "filter, equals, empty node list and special nothing",+ "selector": "$[?@.a == length(@.b)]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ],+ "tags": [+ "function",+ "whitespace"+ ]+ },+ {+ "name": "filter, object data",+ "selector": "$[?@<3]",+ "document": {+ "a": 1,+ "b": 2,+ "c": 3+ },+ "results": [+ [+ 1,+ 2+ ],+ [+ 2,+ 1+ ]+ ],+ "results_paths": [+ [+ "$['a']",+ "$['b']"+ ],+ [+ "$['b']",+ "$['a']"+ ]+ ]+ },+ {+ "name": "filter, and binds more tightly than or",+ "selector": "$[?@.a || @.b && @.c]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2,+ "c": 3+ },+ {+ "c": 3+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2,+ "c": 3+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[4]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, left to right evaluation",+ "selector": "$[?@.a && @.b || @.c]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 1,+ "c": 3+ },+ {+ "b": 1,+ "c": 3+ },+ {+ "c": 3+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 1,+ "c": 3+ },+ {+ "b": 1,+ "c": 3+ },+ {+ "c": 3+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result_paths": [+ "$[2]",+ "$[3]",+ "$[4]",+ "$[5]",+ "$[6]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, group terms, left",+ "selector": "$[?(@.a || @.b) && @.c]",+ "document": [+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 1,+ "c": 3+ },+ {+ "b": 2,+ "c": 3+ },+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1,+ "c": 3+ },+ {+ "b": 2,+ "c": 3+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]",+ "$[6]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, group terms, right",+ "selector": "$[?@.a && (@.b || @.c)]",+ "document": [+ {+ "a": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 1,+ "c": 2+ },+ {+ "b": 2+ },+ {+ "c": 2+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 1,+ "c": 2+ },+ {+ "a": 1,+ "b": 2,+ "c": 3+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]",+ "$[5]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, string literal, single quote in double quotes",+ "selector": "$[?@ == \"quoted' literal\"]",+ "document": [+ "quoted' literal",+ "a",+ "quoted\\' literal"+ ],+ "result": [+ "quoted' literal"+ ],+ "result_paths": [+ "$[0]"+ ]+ },+ {+ "name": "filter, string literal, double quote in single quotes",+ "selector": "$[?@ == 'quoted\" literal']",+ "document": [+ "quoted\" literal",+ "a",+ "quoted\\\" literal",+ "'quoted\" literal'"+ ],+ "result": [+ "quoted\" literal"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, string literal, escaped single quote in single quotes",+ "selector": "$[?@ == 'quoted\\' literal']",+ "document": [+ "quoted' literal",+ "a",+ "quoted\\' literal",+ "'quoted\" literal'"+ ],+ "result": [+ "quoted' literal"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, string literal, escaped double quote in double quotes",+ "selector": "$[?@ == \"quoted\\\" literal\"]",+ "document": [+ "quoted\" literal",+ "a",+ "quoted\\\" literal",+ "'quoted\" literal'"+ ],+ "result": [+ "quoted\" literal"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, literal true must be compared",+ "selector": "$[?true]",+ "invalid_selector": true+ },+ {+ "name": "filter, literal false must be compared",+ "selector": "$[?false]",+ "invalid_selector": true+ },+ {+ "name": "filter, literal string must be compared",+ "selector": "$[?'abc']",+ "invalid_selector": true+ },+ {+ "name": "filter, literal int must be compared",+ "selector": "$[?2]",+ "invalid_selector": true+ },+ {+ "name": "filter, literal float must be compared",+ "selector": "$[?2.2]",+ "invalid_selector": true+ },+ {+ "name": "filter, literal null must be compared",+ "selector": "$[?null]",+ "invalid_selector": true+ },+ {+ "name": "filter, and, literals must be compared",+ "selector": "$[?true && false]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, or, literals must be compared",+ "selector": "$[?true || false]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, and, right hand literal must be compared",+ "selector": "$[?true == false && false]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, or, right hand literal must be compared",+ "selector": "$[?true == false || false]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, and, left hand literal must be compared",+ "selector": "$[?false && true == false]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, or, left hand literal must be compared",+ "selector": "$[?false || true == false]",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "filter, true, incorrectly capitalized",+ "selector": "$[?@==True]",+ "invalid_selector": true,+ "tags": [+ "case"+ ]+ },+ {+ "name": "filter, false, incorrectly capitalized",+ "selector": "$[?@==False]",+ "invalid_selector": true,+ "tags": [+ "case"+ ]+ },+ {+ "name": "filter, null, incorrectly capitalized",+ "selector": "$[?@==Null]",+ "invalid_selector": true,+ "tags": [+ "case"+ ]+ },+ {+ "name": "index selector, first element",+ "selector": "$[0]",+ "document": [+ "first",+ "second"+ ],+ "result": [+ "first"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, second element",+ "selector": "$[1]",+ "document": [+ "first",+ "second"+ ],+ "result": [+ "second"+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, out of bound",+ "selector": "$[2]",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, min exact index",+ "selector": "$[-9007199254740991]",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, max exact index",+ "selector": "$[9007199254740991]",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, min exact index - 1",+ "selector": "$[-9007199254740992]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, max exact index + 1",+ "selector": "$[9007199254740992]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, overflowing index",+ "selector": "$[231584178474632390847141970017375815706539969331281128078915168015826259279872]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, not actually an index, overflowing index leads into general text",+ "selector": "$[231584178474632390847141970017375815706539969331281128078915168SomeRandomText]",+ "invalid_selector": true,+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, negative",+ "selector": "$[-1]",+ "document": [+ "first",+ "second"+ ],+ "result": [+ "second"+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, more negative",+ "selector": "$[-2]",+ "document": [+ "first",+ "second"+ ],+ "result": [+ "first"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, negative out of bound",+ "selector": "$[-3]",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "index"+ ]+ },+ {+ "name": "index selector, on object",+ "selector": "$[0]",+ "document": {+ "foo": 1+ },+ "result": [],+ "result_paths": [],+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, leading 0",+ "selector": "$[01]",+ "invalid_selector": true,+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, decimal",+ "selector": "$[1.0]",+ "invalid_selector": true,+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, plus",+ "selector": "$[+1]",+ "invalid_selector": true,+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, minus space",+ "selector": "$[- 1]",+ "invalid_selector": true,+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "index selector, -0",+ "selector": "$[-0]",+ "invalid_selector": true,+ "tags": [+ "index"+ ]+ },+ {+ "name": "index selector, leading -0",+ "selector": "$[-01]",+ "invalid_selector": true,+ "tags": [+ "index"+ ]+ },+ {+ "name": "name selector, double quotes",+ "selector": "$[\"a\"]",+ "document": {+ "a": "A",+ "b": "B"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['a']"+ ]+ },+ {+ "name": "name selector, double quotes, absent data",+ "selector": "$[\"c\"]",+ "document": {+ "a": "A",+ "b": "B"+ },+ "result": [],+ "result_paths": []+ },+ {+ "name": "name selector, double quotes, array data",+ "selector": "$[\"a\"]",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "name selector, name, double quotes, contains single quote",+ "selector": "$[\"a'\"]",+ "document": {+ "a'": "A",+ "b": "B"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['a\\'']"+ ]+ },+ {+ "name": "name selector, name, double quotes, nested",+ "selector": "$[\"a\"][\"b\"][\"c\"]",+ "document": {+ "a": {+ "b": {+ "c": "C"+ }+ }+ },+ "result": [+ "C"+ ],+ "result_paths": [+ "$['a']['b']['c']"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0000",+ "selector": "$[\"\u0000\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0001",+ "selector": "$[\"\u0001\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0002",+ "selector": "$[\"\u0002\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0003",+ "selector": "$[\"\u0003\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0004",+ "selector": "$[\"\u0004\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0005",+ "selector": "$[\"\u0005\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0006",+ "selector": "$[\"\u0006\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0007",+ "selector": "$[\"\u0007\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0008",+ "selector": "$[\"\b\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0009",+ "selector": "$[\"\t\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+000A",+ "selector": "$[\"\n\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+000B",+ "selector": "$[\"\u000b\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+000C",+ "selector": "$[\"\f\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+000D",+ "selector": "$[\"\r\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+000E",+ "selector": "$[\"\u000e\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+000F",+ "selector": "$[\"\u000f\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0010",+ "selector": "$[\"\u0010\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0011",+ "selector": "$[\"\u0011\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0012",+ "selector": "$[\"\u0012\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0013",+ "selector": "$[\"\u0013\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0014",+ "selector": "$[\"\u0014\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0015",+ "selector": "$[\"\u0015\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0016",+ "selector": "$[\"\u0016\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0017",+ "selector": "$[\"\u0017\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0018",+ "selector": "$[\"\u0018\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0019",+ "selector": "$[\"\u0019\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+001A",+ "selector": "$[\"\u001a\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+001B",+ "selector": "$[\"\u001b\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+001C",+ "selector": "$[\"\u001c\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+001D",+ "selector": "$[\"\u001d\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+001E",+ "selector": "$[\"\u001e\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+001F",+ "selector": "$[\"\u001f\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+0020",+ "selector": "$[\" \"]",+ "document": {+ " ": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$[' ']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, embedded U+007F",+ "selector": "$[\"\"]",+ "document": {+ "": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, supplementary plane character",+ "selector": "$[\"𝄞\"]",+ "document": {+ "𝄞": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['𝄞']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, escaped double quote",+ "selector": "$[\"\\\"\"]",+ "document": {+ "\"": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\"']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped reverse solidus",+ "selector": "$[\"\\\\\"]",+ "document": {+ "\\": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\\\']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped solidus",+ "selector": "$[\"\\/\"]",+ "document": {+ "/": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['/']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped backspace",+ "selector": "$[\"\\b\"]",+ "document": {+ "\b": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\b']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped form feed",+ "selector": "$[\"\\f\"]",+ "document": {+ "\f": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\f']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped line feed",+ "selector": "$[\"\\n\"]",+ "document": {+ "\n": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\n']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped carriage return",+ "selector": "$[\"\\r\"]",+ "document": {+ "\r": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\r']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped tab",+ "selector": "$[\"\\t\"]",+ "document": {+ "\t": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\t']"+ ]+ },+ {+ "name": "name selector, double quotes, escaped ☺, upper case hex",+ "selector": "$[\"\\u263A\"]",+ "document": {+ "☺": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['☺']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, escaped ☺, lower case hex",+ "selector": "$[\"\\u263a\"]",+ "document": {+ "☺": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['☺']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, surrogate pair 𝄞",+ "selector": "$[\"\\uD834\\uDD1E\"]",+ "document": {+ "𝄞": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['𝄞']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, surrogate pair 😀",+ "selector": "$[\"\\uD83D\\uDE00\"]",+ "document": {+ "😀": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['😀']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, before high surrogates",+ "selector": "$[\"\\uD7FF\\uD7FF\"]",+ "document": {+ "": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, after low surrogates",+ "selector": "$[\"\\uE000\\uE000\"]",+ "document": {+ "": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, invalid escaped single quote",+ "selector": "$[\"\\'\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, embedded double quote",+ "selector": "$[\"\"\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, incomplete escape",+ "selector": "$[\"\\\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, escape at end of line",+ "selector": "$[\"\\\n\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, question mark escape",+ "selector": "$[\"\\?\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, bell escape",+ "selector": "$[\"\\a\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, vertical tab escape",+ "selector": "$[\"\\v\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, 0 escape",+ "selector": "$[\"\\0\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, x escape",+ "selector": "$[\"\\x12\"]",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, n escape",+ "selector": "$[\"\\N{LATIN CAPITAL LETTER A}\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape no hex",+ "selector": "$[\"\\u\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape too few hex",+ "selector": "$[\"\\u123\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape upper u",+ "selector": "$[\"\\U1234\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape upper u long",+ "selector": "$[\"\\U0010FFFF\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape plus",+ "selector": "$[\"\\u+1234\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape brackets",+ "selector": "$[\"\\u{1234}\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, unicode escape brackets long",+ "selector": "$[\"\\u{10ffff}\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, single high surrogate",+ "selector": "$[\"\\uD800\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, single low surrogate",+ "selector": "$[\"\\uDC00\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, high high surrogate",+ "selector": "$[\"\\uD800\\uD800\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, low low surrogate",+ "selector": "$[\"\\uDC00\\uDC00\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, surrogate non-surrogate",+ "selector": "$[\"\\uD800\\u1234\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, non-surrogate surrogate",+ "selector": "$[\"\\u1234\\uDC00\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, surrogate supplementary",+ "selector": "$[\"\\uD800𝄞\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, supplementary surrogate",+ "selector": "$[\"𝄞\\uDC00\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, double quotes, surrogate incomplete low",+ "selector": "$[\"\\uD800\\uDC0\"]",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes",+ "selector": "$['a']",+ "document": {+ "a": "A",+ "b": "B"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['a']"+ ]+ },+ {+ "name": "name selector, single quotes, absent data",+ "selector": "$['c']",+ "document": {+ "a": "A",+ "b": "B"+ },+ "result": [],+ "result_paths": []+ },+ {+ "name": "name selector, single quotes, array data",+ "selector": "$['a']",+ "document": [+ "first",+ "second"+ ],+ "result": [],+ "result_paths": []+ },+ {+ "name": "name selector, single quotes, embedded U+0000",+ "selector": "$['\u0000']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0001",+ "selector": "$['\u0001']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0002",+ "selector": "$['\u0002']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0003",+ "selector": "$['\u0003']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0004",+ "selector": "$['\u0004']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0005",+ "selector": "$['\u0005']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0006",+ "selector": "$['\u0006']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0007",+ "selector": "$['\u0007']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0008",+ "selector": "$['\b']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0009",+ "selector": "$['\t']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+000A",+ "selector": "$['\n']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+000B",+ "selector": "$['\u000b']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+000C",+ "selector": "$['\f']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+000D",+ "selector": "$['\r']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+000E",+ "selector": "$['\u000e']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+000F",+ "selector": "$['\u000f']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0010",+ "selector": "$['\u0010']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0011",+ "selector": "$['\u0011']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0012",+ "selector": "$['\u0012']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0013",+ "selector": "$['\u0013']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0014",+ "selector": "$['\u0014']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0015",+ "selector": "$['\u0015']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0016",+ "selector": "$['\u0016']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0017",+ "selector": "$['\u0017']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0018",+ "selector": "$['\u0018']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0019",+ "selector": "$['\u0019']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+001A",+ "selector": "$['\u001a']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+001B",+ "selector": "$['\u001b']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+001C",+ "selector": "$['\u001c']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+001D",+ "selector": "$['\u001d']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+001E",+ "selector": "$['\u001e']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+001F",+ "selector": "$['\u001f']",+ "invalid_selector": true,+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, embedded U+0020",+ "selector": "$[' ']",+ "document": {+ " ": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$[' ']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, escaped single quote",+ "selector": "$['\\'']",+ "document": {+ "'": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\'']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped reverse solidus",+ "selector": "$['\\\\']",+ "document": {+ "\\": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\\\']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped solidus",+ "selector": "$['\\/']",+ "document": {+ "/": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['/']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, escaped backspace",+ "selector": "$['\\b']",+ "document": {+ "\b": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\b']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped form feed",+ "selector": "$['\\f']",+ "document": {+ "\f": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\f']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped line feed",+ "selector": "$['\\n']",+ "document": {+ "\n": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\n']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped carriage return",+ "selector": "$['\\r']",+ "document": {+ "\r": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\r']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped tab",+ "selector": "$['\\t']",+ "document": {+ "\t": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['\\t']"+ ]+ },+ {+ "name": "name selector, single quotes, escaped ☺, upper case hex",+ "selector": "$['\\u263A']",+ "document": {+ "☺": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['☺']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, escaped ☺, lower case hex",+ "selector": "$['\\u263a']",+ "document": {+ "☺": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['☺']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, surrogate pair 𝄞",+ "selector": "$['\\uD834\\uDD1E']",+ "document": {+ "𝄞": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['𝄞']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, surrogate pair 😀",+ "selector": "$['\\uD83D\\uDE00']",+ "document": {+ "😀": "A"+ },+ "result": [+ "A"+ ],+ "result_paths": [+ "$['😀']"+ ],+ "tags": [+ "unicode"+ ]+ },+ {+ "name": "name selector, single quotes, invalid escaped double quote",+ "selector": "$['\\\"']",+ "invalid_selector": true+ },+ {+ "name": "name selector, single quotes, embedded single quote",+ "selector": "$[''']",+ "invalid_selector": true+ },+ {+ "name": "name selector, single quotes, incomplete escape",+ "selector": "$['\\']",+ "invalid_selector": true+ },+ {+ "name": "name selector, double quotes, empty",+ "selector": "$[\"\"]",+ "document": {+ "a": "A",+ "b": "B",+ "": "C"+ },+ "result": [+ "C"+ ],+ "result_paths": [+ "$['']"+ ]+ },+ {+ "name": "name selector, single quotes, empty",+ "selector": "$['']",+ "document": {+ "a": "A",+ "b": "B",+ "": "C"+ },+ "result": [+ "C"+ ],+ "result_paths": [+ "$['']"+ ]+ },+ {+ "name": "slice selector, slice selector",+ "selector": "$[1:3]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1,+ 2+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, slice selector with step",+ "selector": "$[1:6:2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1,+ 3,+ 5+ ],+ "result_paths": [+ "$[1]",+ "$[3]",+ "$[5]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, slice selector with everything omitted, short form",+ "selector": "$[:]",+ "document": [+ 0,+ 1,+ 2,+ 3+ ],+ "result": [+ 0,+ 1,+ 2,+ 3+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, slice selector with everything omitted, long form",+ "selector": "$[::]",+ "document": [+ 0,+ 1,+ 2,+ 3+ ],+ "result": [+ 0,+ 1,+ 2,+ 3+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, slice selector with start omitted",+ "selector": "$[:2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0,+ 1+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, slice selector with start and end omitted",+ "selector": "$[::2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0,+ 2,+ 4,+ 6,+ 8+ ],+ "result_paths": [+ "$[0]",+ "$[2]",+ "$[4]",+ "$[6]",+ "$[8]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative step with default start and end",+ "selector": "$[::-1]",+ "document": [+ 0,+ 1,+ 2,+ 3+ ],+ "result": [+ 3,+ 2,+ 1,+ 0+ ],+ "result_paths": [+ "$[3]",+ "$[2]",+ "$[1]",+ "$[0]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative step with default start",+ "selector": "$[:0:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3+ ],+ "result": [+ 3,+ 2,+ 1+ ],+ "result_paths": [+ "$[3]",+ "$[2]",+ "$[1]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative step with default end",+ "selector": "$[2::-1]",+ "document": [+ 0,+ 1,+ 2,+ 3+ ],+ "result": [+ 2,+ 1,+ 0+ ],+ "result_paths": [+ "$[2]",+ "$[1]",+ "$[0]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, larger negative step",+ "selector": "$[::-2]",+ "document": [+ 0,+ 1,+ 2,+ 3+ ],+ "result": [+ 3,+ 1+ ],+ "result_paths": [+ "$[3]",+ "$[1]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative range with default step",+ "selector": "$[-1:-3]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative range with negative step",+ "selector": "$[-1:-3:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9,+ 8+ ],+ "result_paths": [+ "$[9]",+ "$[8]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative range with larger negative step",+ "selector": "$[-1:-6:-2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9,+ 7,+ 5+ ],+ "result_paths": [+ "$[9]",+ "$[7]",+ "$[5]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, larger negative range with larger negative step",+ "selector": "$[-1:-7:-2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9,+ 7,+ 5+ ],+ "result_paths": [+ "$[9]",+ "$[7]",+ "$[5]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative from, positive to",+ "selector": "$[-5:7]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 5,+ 6+ ],+ "result_paths": [+ "$[5]",+ "$[6]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative from",+ "selector": "$[-2:]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 8,+ 9+ ],+ "result_paths": [+ "$[8]",+ "$[9]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, positive from, negative to",+ "selector": "$[1:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8+ ],+ "result_paths": [+ "$[1]",+ "$[2]",+ "$[3]",+ "$[4]",+ "$[5]",+ "$[6]",+ "$[7]",+ "$[8]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative from, positive to, negative step",+ "selector": "$[-1:1:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9,+ 8,+ 7,+ 6,+ 5,+ 4,+ 3,+ 2+ ],+ "result_paths": [+ "$[9]",+ "$[8]",+ "$[7]",+ "$[6]",+ "$[5]",+ "$[4]",+ "$[3]",+ "$[2]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, positive from, negative to, negative step",+ "selector": "$[7:-5:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 7,+ 6+ ],+ "result_paths": [+ "$[7]",+ "$[6]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, in serial, on nested array",+ "selector": "$[1:3][1:2]",+ "document": [+ [+ "a",+ "b",+ "c"+ ],+ [+ "d",+ "e",+ "f"+ ],+ [+ "g",+ "h",+ "i"+ ]+ ],+ "result": [+ "e",+ "h"+ ],+ "result_paths": [+ "$[1][1]",+ "$[2][1]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, in serial, on flat array",+ "selector": "$[1:3][::]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative from, negative to, positive step",+ "selector": "$[-5:-2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 5,+ 6,+ 7+ ],+ "result_paths": [+ "$[5]",+ "$[6]",+ "$[7]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, too many colons",+ "selector": "$[1:2:3:4]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, non-integer array index",+ "selector": "$[1:2:a]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, zero step",+ "selector": "$[1:2:0]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, empty range",+ "selector": "$[2:2]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, slice selector with everything omitted with empty array",+ "selector": "$[:]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, negative step with empty array",+ "selector": "$[::-1]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, maximal range with positive step",+ "selector": "$[0:10]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result_paths": [+ "$[0]",+ "$[1]",+ "$[2]",+ "$[3]",+ "$[4]",+ "$[5]",+ "$[6]",+ "$[7]",+ "$[8]",+ "$[9]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, maximal range with negative step",+ "selector": "$[9:0:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9,+ 8,+ 7,+ 6,+ 5,+ 4,+ 3,+ 2,+ 1+ ],+ "result_paths": [+ "$[9]",+ "$[8]",+ "$[7]",+ "$[6]",+ "$[5]",+ "$[4]",+ "$[3]",+ "$[2]",+ "$[1]"+ ],+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, excessively large to value",+ "selector": "$[2:113667776004]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result_paths": [+ "$[2]",+ "$[3]",+ "$[4]",+ "$[5]",+ "$[6]",+ "$[7]",+ "$[8]",+ "$[9]"+ ],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, excessively small from value",+ "selector": "$[-113667776004:1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 0+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, excessively large from value with negative step",+ "selector": "$[113667776004:0:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9,+ 8,+ 7,+ 6,+ 5,+ 4,+ 3,+ 2,+ 1+ ],+ "result_paths": [+ "$[9]",+ "$[8]",+ "$[7]",+ "$[6]",+ "$[5]",+ "$[4]",+ "$[3]",+ "$[2]",+ "$[1]"+ ],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, excessively small to value with negative step",+ "selector": "$[3:-113667776004:-1]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 3,+ 2,+ 1,+ 0+ ],+ "result_paths": [+ "$[3]",+ "$[2]",+ "$[1]",+ "$[0]"+ ],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, excessively large step",+ "selector": "$[1:10:113667776004]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 1+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, excessively small step",+ "selector": "$[-1:-10:-113667776004]",+ "document": [+ 0,+ 1,+ 2,+ 3,+ 4,+ 5,+ 6,+ 7,+ 8,+ 9+ ],+ "result": [+ 9+ ],+ "result_paths": [+ "$[9]"+ ],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, start, min exact",+ "selector": "$[-9007199254740991::]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, start, max exact",+ "selector": "$[9007199254740991::]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, start, min exact - 1",+ "selector": "$[-9007199254740992::]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, start, max exact + 1",+ "selector": "$[9007199254740992::]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, end, min exact",+ "selector": "$[:-9007199254740991:]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, end, max exact",+ "selector": "$[:9007199254740991:]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, end, min exact - 1",+ "selector": "$[:-9007199254740992:]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, end, max exact + 1",+ "selector": "$[:9007199254740992:]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, step, min exact",+ "selector": "$[::-9007199254740991]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, step, max exact",+ "selector": "$[::9007199254740991]",+ "document": [],+ "result": [],+ "result_paths": [],+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, step, min exact - 1",+ "selector": "$[::-9007199254740992]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, step, max exact + 1",+ "selector": "$[::9007199254740992]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, overflowing to value",+ "selector": "$[2:231584178474632390847141970017375815706539969331281128078915168015826259279872]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, underflowing from value",+ "selector": "$[-231584178474632390847141970017375815706539969331281128078915168015826259279872:1]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, overflowing from value with negative step",+ "selector": "$[231584178474632390847141970017375815706539969331281128078915168015826259279872:0:-1]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, underflowing to value with negative step",+ "selector": "$[3:-231584178474632390847141970017375815706539969331281128078915168015826259279872:-1]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, overflowing step",+ "selector": "$[1:10:231584178474632390847141970017375815706539969331281128078915168015826259279872]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, underflowing step",+ "selector": "$[-1:-10:-231584178474632390847141970017375815706539969331281128078915168015826259279872]",+ "invalid_selector": true,+ "tags": [+ "boundary",+ "slice"+ ]+ },+ {+ "name": "slice selector, start, leading 0",+ "selector": "$[01::]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, start, decimal",+ "selector": "$[1.0::]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, start, plus",+ "selector": "$[+1::]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, start, minus space",+ "selector": "$[- 1::]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, start, -0",+ "selector": "$[-0::]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, start, leading -0",+ "selector": "$[-01::]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, end, leading 0",+ "selector": "$[:01:]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, end, decimal",+ "selector": "$[:1.0:]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, end, plus",+ "selector": "$[:+1:]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, end, minus space",+ "selector": "$[:- 1:]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, end, -0",+ "selector": "$[:-0:]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, end, leading -0",+ "selector": "$[:-01:]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, step, leading 0",+ "selector": "$[::01]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, step, decimal",+ "selector": "$[::1.0]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, step, plus",+ "selector": "$[::+1]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, step, minus space",+ "selector": "$[::- 1]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, step, -0",+ "selector": "$[::-0]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "slice selector, step, leading -0",+ "selector": "$[::-01]",+ "invalid_selector": true,+ "tags": [+ "slice"+ ]+ },+ {+ "name": "functions, count, count function",+ "selector": "$[?count(@..*)>2]",+ "document": [+ {+ "a": [+ 1,+ 2,+ 3+ ]+ },+ {+ "a": [+ 1+ ],+ "d": "f"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": [+ 1,+ 2,+ 3+ ]+ },+ {+ "a": [+ 1+ ],+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, single-node arg",+ "selector": "$[?count(@.a)>1]",+ "document": [+ {+ "a": [+ 1,+ 2,+ 3+ ]+ },+ {+ "a": [+ 1+ ],+ "d": "f"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, multiple-selector arg",+ "selector": "$[?count(@['a','d'])>1]",+ "document": [+ {+ "a": [+ 1,+ 2,+ 3+ ]+ },+ {+ "a": [+ 1+ ],+ "d": "f"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result": [+ {+ "a": [+ 1+ ],+ "d": "f"+ },+ {+ "a": 1,+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]",+ "$[2]"+ ],+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, non-query arg, number",+ "selector": "$[?count(1)>2]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, non-query arg, string",+ "selector": "$[?count('string')>2]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, non-query arg, true",+ "selector": "$[?count(true)>2]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, non-query arg, false",+ "selector": "$[?count(false)>2]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, non-query arg, null",+ "selector": "$[?count(null)>2]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, result must be compared",+ "selector": "$[?count(@..*)]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, no params",+ "selector": "$[?count()==1]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, count, too many params",+ "selector": "$[?count(@.a,@.b)==1]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function"+ ]+ },+ {+ "name": "functions, length, string data",+ "selector": "$[?length(@.a)>=2]",+ "document": [+ {+ "a": "ab"+ },+ {+ "a": "d"+ }+ ],+ "result": [+ {+ "a": "ab"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, string data, unicode",+ "selector": "$[?length(@)==2]",+ "document": [+ "☺",+ "☺☺",+ "☺☺☺",+ "ж",+ "жж",+ "жжж",+ "磨",+ "阿美",+ "形声字"+ ],+ "result": [+ "☺☺",+ "жж",+ "阿美"+ ],+ "result_paths": [+ "$[1]",+ "$[4]",+ "$[7]"+ ],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, array data",+ "selector": "$[?length(@.a)>=2]",+ "document": [+ {+ "a": [+ 1,+ 2,+ 3+ ]+ },+ {+ "a": [+ 1+ ]+ }+ ],+ "result": [+ {+ "a": [+ 1,+ 2,+ 3+ ]+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, missing data",+ "selector": "$[?length(@.a)>=2]",+ "document": [+ {+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, number arg",+ "selector": "$[?length(1)>=2]",+ "document": [+ {+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, true arg",+ "selector": "$[?length(true)>=2]",+ "document": [+ {+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, false arg",+ "selector": "$[?length(false)>=2]",+ "document": [+ {+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, null arg",+ "selector": "$[?length(null)>=2]",+ "document": [+ {+ "d": "f"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, result must be compared",+ "selector": "$[?length(@.a)]",+ "invalid_selector": true,+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, no params",+ "selector": "$[?length()==1]",+ "invalid_selector": true,+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, too many params",+ "selector": "$[?length(@.a,@.b)==1]",+ "invalid_selector": true,+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, non-singular query arg",+ "selector": "$[?length(@.*)<3]",+ "invalid_selector": true,+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, arg is a function expression",+ "selector": "$.values[?length(@.a)==length(value($..c))]",+ "document": {+ "c": "cd",+ "values": [+ {+ "a": "ab"+ },+ {+ "a": "d"+ }+ ]+ },+ "result": [+ {+ "a": "ab"+ }+ ],+ "result_paths": [+ "$['values'][0]"+ ],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, length, arg is special nothing",+ "selector": "$[?length(value(@.a))>0]",+ "document": [+ {+ "a": "ab"+ },+ {+ "c": "d"+ },+ {+ "a": null+ }+ ],+ "result": [+ {+ "a": "ab"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length"+ ]+ },+ {+ "name": "functions, match, found match",+ "selector": "$[?match(@.a, 'a.*')]",+ "document": [+ {+ "a": "ab"+ }+ ],+ "result": [+ {+ "a": "ab"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, double quotes",+ "selector": "$[?match(@.a, \"a.*\")]",+ "document": [+ {+ "a": "ab"+ }+ ],+ "result": [+ {+ "a": "ab"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, regex from the document",+ "selector": "$.values[?match(@, $.regex)]",+ "document": {+ "regex": "b.?b",+ "values": [+ "abc",+ "bcd",+ "bab",+ "bba",+ "bbab",+ "b",+ true,+ [],+ {}+ ]+ },+ "result": [+ "bab"+ ],+ "result_paths": [+ "$['values'][2]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, don't select match",+ "selector": "$[?!match(@.a, 'a.*')]",+ "document": [+ {+ "a": "ab"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, not a match",+ "selector": "$[?match(@.a, 'a.*')]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, select non-match",+ "selector": "$[?!match(@.a, 'a.*')]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [+ {+ "a": "bc"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, non-string first arg",+ "selector": "$[?match(1, 'a.*')]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, non-string second arg",+ "selector": "$[?match(@.a, 1)]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, filter, match function, unicode char class, uppercase",+ "selector": "$[?match(@, '\\\\p{Lu}')]",+ "document": [+ "ж",+ "Ж",+ "1",+ "жЖ",+ true,+ [],+ {}+ ],+ "result": [+ "Ж"+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, filter, match function, unicode char class negated, uppercase",+ "selector": "$[?match(@, '\\\\P{Lu}')]",+ "document": [+ "ж",+ "Ж",+ "1",+ true,+ [],+ {}+ ],+ "result": [+ "ж",+ "1"+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, filter, match function, unicode, surrogate pair",+ "selector": "$[?match(@, 'a.b')]",+ "document": [+ "a𐄁b",+ "ab",+ "1",+ true,+ [],+ {}+ ],+ "result": [+ "a𐄁b"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, dot matcher on \\u2028",+ "selector": "$[?match(@, '.')]",+ "document": [+ " ",+ "\r",+ "\n",+ true,+ [],+ {}+ ],+ "result": [+ " "+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, dot matcher on \\u2029",+ "selector": "$[?match(@, '.')]",+ "document": [+ " ",+ "\r",+ "\n",+ true,+ [],+ {}+ ],+ "result": [+ " "+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, result cannot be compared",+ "selector": "$[?match(@.a, 'a.*')==true]",+ "invalid_selector": true,+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, too few params",+ "selector": "$[?match(@.a)==1]",+ "invalid_selector": true,+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, too many params",+ "selector": "$[?match(@.a,@.b,@.c)==1]",+ "invalid_selector": true,+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, arg is a function expression",+ "selector": "$.values[?match(@.a, value($..['regex']))]",+ "document": {+ "regex": "a.*",+ "values": [+ {+ "a": "ab"+ },+ {+ "a": "ba"+ }+ ]+ },+ "result": [+ {+ "a": "ab"+ }+ ],+ "result_paths": [+ "$['values'][0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, dot in character class",+ "selector": "$[?match(@, 'a[.b]c')]",+ "document": [+ "abc",+ "a.c",+ "axc"+ ],+ "result": [+ "abc",+ "a.c"+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, escaped dot",+ "selector": "$[?match(@, 'a\\\\.c')]",+ "document": [+ "abc",+ "a.c",+ "axc"+ ],+ "result": [+ "a.c"+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, escaped backslash before dot",+ "selector": "$[?match(@, 'a\\\\\\\\.c')]",+ "document": [+ "abc",+ "a.c",+ "axc",+ "a\\ c"+ ],+ "result": [+ "a\\ c"+ ],+ "result_paths": [+ "$[3]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, escaped left square bracket",+ "selector": "$[?match(@, 'a\\\\[.c')]",+ "document": [+ "abc",+ "a.c",+ "a[ c"+ ],+ "result": [+ "a[ c"+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, escaped right square bracket",+ "selector": "$[?match(@, 'a[\\\\].]c')]",+ "document": [+ "abc",+ "a.c",+ "a c",+ "a]c"+ ],+ "result": [+ "a.c",+ "a]c"+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, explicit caret",+ "selector": "$[?match(@, '^ab.*')]",+ "document": [+ "abc",+ "axc",+ "ab",+ "xab"+ ],+ "result": [+ "abc",+ "ab"+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, match, explicit dollar",+ "selector": "$[?match(@, '.*bc$')]",+ "document": [+ "abc",+ "axc",+ "ab",+ "abcx"+ ],+ "result": [+ "abc"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "match"+ ]+ },+ {+ "name": "functions, search, at the end",+ "selector": "$[?search(@.a, 'a.*')]",+ "document": [+ {+ "a": "the end is ab"+ }+ ],+ "result": [+ {+ "a": "the end is ab"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, double quotes",+ "selector": "$[?search(@.a, \"a.*\")]",+ "document": [+ {+ "a": "the end is ab"+ }+ ],+ "result": [+ {+ "a": "the end is ab"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, at the start",+ "selector": "$[?search(@.a, 'a.*')]",+ "document": [+ {+ "a": "ab is at the start"+ }+ ],+ "result": [+ {+ "a": "ab is at the start"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, in the middle",+ "selector": "$[?search(@.a, 'a.*')]",+ "document": [+ {+ "a": "contains two matches"+ }+ ],+ "result": [+ {+ "a": "contains two matches"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, regex from the document",+ "selector": "$.values[?search(@, $.regex)]",+ "document": {+ "regex": "b.?b",+ "values": [+ "abc",+ "bcd",+ "bab",+ "bba",+ "bbab",+ "b",+ true,+ [],+ {}+ ]+ },+ "result": [+ "bab",+ "bba",+ "bbab"+ ],+ "result_paths": [+ "$['values'][2]",+ "$['values'][3]",+ "$['values'][4]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, don't select match",+ "selector": "$[?!search(@.a, 'a.*')]",+ "document": [+ {+ "a": "contains two matches"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, not a match",+ "selector": "$[?search(@.a, 'a.*')]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, select non-match",+ "selector": "$[?!search(@.a, 'a.*')]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [+ {+ "a": "bc"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, non-string first arg",+ "selector": "$[?search(1, 'a.*')]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, non-string second arg",+ "selector": "$[?search(@.a, 1)]",+ "document": [+ {+ "a": "bc"+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, filter, search function, unicode char class, uppercase",+ "selector": "$[?search(@, '\\\\p{Lu}')]",+ "document": [+ "ж",+ "Ж",+ "1",+ "жЖ",+ true,+ [],+ {}+ ],+ "result": [+ "Ж",+ "жЖ"+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, filter, search function, unicode char class negated, uppercase",+ "selector": "$[?search(@, '\\\\P{Lu}')]",+ "document": [+ "ж",+ "Ж",+ "1",+ true,+ [],+ {}+ ],+ "result": [+ "ж",+ "1"+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, filter, search function, unicode, surrogate pair",+ "selector": "$[?search(@, 'a.b')]",+ "document": [+ "a𐄁bc",+ "abc",+ "1",+ true,+ [],+ {}+ ],+ "result": [+ "a𐄁bc"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, dot matcher on \\u2028",+ "selector": "$[?search(@, '.')]",+ "document": [+ " ",+ "\r \n",+ "\r",+ "\n",+ true,+ [],+ {}+ ],+ "result": [+ " ",+ "\r \n"+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, dot matcher on \\u2029",+ "selector": "$[?search(@, '.')]",+ "document": [+ " ",+ "\r \n",+ "\r",+ "\n",+ true,+ [],+ {}+ ],+ "result": [+ " ",+ "\r \n"+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, result cannot be compared",+ "selector": "$[?search(@.a, 'a.*')==true]",+ "invalid_selector": true,+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, too few params",+ "selector": "$[?search(@.a)]",+ "invalid_selector": true,+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, too many params",+ "selector": "$[?search(@.a,@.b,@.c)]",+ "invalid_selector": true,+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, arg is a function expression",+ "selector": "$.values[?search(@, value($..['regex']))]",+ "document": {+ "regex": "b.?b",+ "values": [+ "abc",+ "bcd",+ "bab",+ "bba",+ "bbab",+ "b",+ true,+ [],+ {}+ ]+ },+ "result": [+ "bab",+ "bba",+ "bbab"+ ],+ "result_paths": [+ "$['values'][2]",+ "$['values'][3]",+ "$['values'][4]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, dot in character class",+ "selector": "$[?search(@, 'a[.b]c')]",+ "document": [+ "x abc y",+ "x a.c y",+ "x axc y"+ ],+ "result": [+ "x abc y",+ "x a.c y"+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, escaped dot",+ "selector": "$[?search(@, 'a\\\\.c')]",+ "document": [+ "x abc y",+ "x a.c y",+ "x axc y"+ ],+ "result": [+ "x a.c y"+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, escaped backslash before dot",+ "selector": "$[?search(@, 'a\\\\\\\\.c')]",+ "document": [+ "x abc y",+ "x a.c y",+ "x axc y",+ "x a\\ c y"+ ],+ "result": [+ "x a\\ c y"+ ],+ "result_paths": [+ "$[3]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, escaped left square bracket",+ "selector": "$[?search(@, 'a\\\\[.c')]",+ "document": [+ "x abc y",+ "x a.c y",+ "x a[ c y"+ ],+ "result": [+ "x a[ c y"+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, search, escaped right square bracket",+ "selector": "$[?search(@, 'a[\\\\].]c')]",+ "document": [+ "x abc y",+ "x a.c y",+ "x a c y",+ "x a]c y"+ ],+ "result": [+ "x a.c y",+ "x a]c y"+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "function",+ "search"+ ]+ },+ {+ "name": "functions, value, single-value nodelist",+ "selector": "$[?value(@.*)==4]",+ "document": [+ [+ 4+ ],+ {+ "foo": 4+ },+ [+ 5+ ],+ {+ "foo": 5+ },+ 4+ ],+ "result": [+ [+ 4+ ],+ {+ "foo": 4+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "function",+ "value"+ ]+ },+ {+ "name": "functions, value, multi-value nodelist",+ "selector": "$[?value(@.*)==4]",+ "document": [+ [+ 4,+ 4+ ],+ {+ "foo": 4,+ "bar": 4+ }+ ],+ "result": [],+ "result_paths": [],+ "tags": [+ "function",+ "value"+ ]+ },+ {+ "name": "functions, value, too few params",+ "selector": "$[?value()==4]",+ "invalid_selector": true,+ "tags": [+ "function",+ "value"+ ]+ },+ {+ "name": "functions, value, too many params",+ "selector": "$[?value(@.a,@.b)==4]",+ "invalid_selector": true,+ "tags": [+ "function",+ "value"+ ]+ },+ {+ "name": "functions, value, result must be compared",+ "selector": "$[?value(@.a)]",+ "invalid_selector": true,+ "tags": [+ "function",+ "value"+ ]+ },+ {+ "name": "whitespace, filter, space between question mark and expression",+ "selector": "$[? @.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, newline between question mark and expression",+ "selector": "$[?\n@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, tab between question mark and expression",+ "selector": "$[?\t@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, return between question mark and expression",+ "selector": "$[?\r@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, space between question mark and parenthesized expression",+ "selector": "$[? (@.a)]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, newline between question mark and parenthesized expression",+ "selector": "$[?\n(@.a)]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, tab between question mark and parenthesized expression",+ "selector": "$[?\t(@.a)]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, return between question mark and parenthesized expression",+ "selector": "$[?\r(@.a)]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, space between parenthesized expression and bracket",+ "selector": "$[?(@.a) ]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, newline between parenthesized expression and bracket",+ "selector": "$[?(@.a)\n]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, tab between parenthesized expression and bracket",+ "selector": "$[?(@.a)\t]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, return between parenthesized expression and bracket",+ "selector": "$[?(@.a)\r]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, space between bracket and question mark",+ "selector": "$[ ?@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, newline between bracket and question mark",+ "selector": "$[\n?@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, tab between bracket and question mark",+ "selector": "$[\t?@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, filter, return between bracket and question mark",+ "selector": "$[\r?@.a]",+ "document": [+ {+ "a": "b",+ "d": "e"+ },+ {+ "b": "c",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "b",+ "d": "e"+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, space between function name and parenthesis",+ "selector": "$[?count (@.*)==1]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newline between function name and parenthesis",+ "selector": "$[?count\n(@.*)==1]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tab between function name and parenthesis",+ "selector": "$[?count\t(@.*)==1]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, return between function name and parenthesis",+ "selector": "$[?count\r(@.*)==1]",+ "invalid_selector": true,+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, space between parenthesis and arg",+ "selector": "$[?count( @.*)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newline between parenthesis and arg",+ "selector": "$[?count(\n@.*)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tab between parenthesis and arg",+ "selector": "$[?count(\t@.*)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, return between parenthesis and arg",+ "selector": "$[?count(\r@.*)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, space between arg and comma",+ "selector": "$[?search(@ ,'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newline between arg and comma",+ "selector": "$[?search(@\n,'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tab between arg and comma",+ "selector": "$[?search(@\t,'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, return between arg and comma",+ "selector": "$[?search(@\r,'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, space between comma and arg",+ "selector": "$[?search(@, '[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newline between comma and arg",+ "selector": "$[?search(@,\n'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tab between comma and arg",+ "selector": "$[?search(@,\t'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, return between comma and arg",+ "selector": "$[?search(@,\r'[a-z]+')]",+ "document": [+ "foo",+ "123"+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, space between arg and parenthesis",+ "selector": "$[?count(@.* )==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "function",+ "search",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newline between arg and parenthesis",+ "selector": "$[?count(@.*\n)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tab between arg and parenthesis",+ "selector": "$[?count(@.*\t)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, return between arg and parenthesis",+ "selector": "$[?count(@.*\r)==1]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "count",+ "function",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, spaces in a relative singular selector",+ "selector": "$[?length(@ .a .b) == 3]",+ "document": [+ {+ "a": {+ "b": "foo"+ }+ },+ {}+ ],+ "result": [+ {+ "a": {+ "b": "foo"+ }+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newlines in a relative singular selector",+ "selector": "$[?length(@\n.a\n.b) == 3]",+ "document": [+ {+ "a": {+ "b": "foo"+ }+ },+ {}+ ],+ "result": [+ {+ "a": {+ "b": "foo"+ }+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tabs in a relative singular selector",+ "selector": "$[?length(@\t.a\t.b) == 3]",+ "document": [+ {+ "a": {+ "b": "foo"+ }+ },+ {}+ ],+ "result": [+ {+ "a": {+ "b": "foo"+ }+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, returns in a relative singular selector",+ "selector": "$[?length(@\r.a\r.b) == 3]",+ "document": [+ {+ "a": {+ "b": "foo"+ }+ },+ {}+ ],+ "result": [+ {+ "a": {+ "b": "foo"+ }+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, spaces in an absolute singular selector",+ "selector": "$..[?length(@)==length($ [0] .a)]",+ "document": [+ {+ "a": "foo"+ },+ {}+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]['a']"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, newlines in an absolute singular selector",+ "selector": "$..[?length(@)==length($\n[0]\n.a)]",+ "document": [+ {+ "a": "foo"+ },+ {}+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]['a']"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, tabs in an absolute singular selector",+ "selector": "$..[?length(@)==length($\t[0]\t.a)]",+ "document": [+ {+ "a": "foo"+ },+ {}+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]['a']"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, functions, returns in an absolute singular selector",+ "selector": "$..[?length(@)==length($\r[0]\r.a)]",+ "document": [+ {+ "a": "foo"+ },+ {}+ ],+ "result": [+ "foo"+ ],+ "result_paths": [+ "$[0]['a']"+ ],+ "tags": [+ "function",+ "length",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before ||",+ "selector": "$[?@.a ||@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before ||",+ "selector": "$[?@.a\n||@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before ||",+ "selector": "$[?@.a\t||@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before ||",+ "selector": "$[?@.a\r||@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after ||",+ "selector": "$[?@.a|| @.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after ||",+ "selector": "$[?@.a||\n@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after ||",+ "selector": "$[?@.a||\t@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after ||",+ "selector": "$[?@.a||\r@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "c": 3+ }+ ],+ "result": [+ {+ "a": 1+ },+ {+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before &&",+ "selector": "$[?@.a &&@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before &&",+ "selector": "$[?@.a\n&&@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before &&",+ "selector": "$[?@.a\t&&@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before &&",+ "selector": "$[?@.a\r&&@.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after &&",+ "selector": "$[?@.a&& @.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after &&",+ "selector": "$[?@.a&& @.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after &&",+ "selector": "$[?@.a&& @.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after &&",+ "selector": "$[?@.a&& @.b]",+ "document": [+ {+ "a": 1+ },+ {+ "b": 2+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before ==",+ "selector": "$[?@.a ==@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before ==",+ "selector": "$[?@.a\n==@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before ==",+ "selector": "$[?@.a\t==@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before ==",+ "selector": "$[?@.a\r==@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after ==",+ "selector": "$[?@.a== @.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after ==",+ "selector": "$[?@.a==\n@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after ==",+ "selector": "$[?@.a==\t@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after ==",+ "selector": "$[?@.a==\r@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ }+ ],+ "result_paths": [+ "$[0]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before !=",+ "selector": "$[?@.a !=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before !=",+ "selector": "$[?@.a\n!=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before !=",+ "selector": "$[?@.a\t!=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before !=",+ "selector": "$[?@.a\r!=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after !=",+ "selector": "$[?@.a!= @.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after !=",+ "selector": "$[?@.a!=\n@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after !=",+ "selector": "$[?@.a!=\t@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after !=",+ "selector": "$[?@.a!=\r@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before <",+ "selector": "$[?@.a <@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before <",+ "selector": "$[?@.a\n<@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before <",+ "selector": "$[?@.a\t<@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before <",+ "selector": "$[?@.a\r<@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after <",+ "selector": "$[?@.a< @.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after <",+ "selector": "$[?@.a<\n@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after <",+ "selector": "$[?@.a<\t@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after <",+ "selector": "$[?@.a<\r@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before >",+ "selector": "$[?@.b >@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before >",+ "selector": "$[?@.b\n>@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before >",+ "selector": "$[?@.b\t>@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before >",+ "selector": "$[?@.b\r>@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after >",+ "selector": "$[?@.b> @.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after >",+ "selector": "$[?@.b>\n@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after >",+ "selector": "$[?@.b>\t@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after >",+ "selector": "$[?@.b>\r@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before <=",+ "selector": "$[?@.a <=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before <=",+ "selector": "$[?@.a\n<=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before <=",+ "selector": "$[?@.a\t<=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before <=",+ "selector": "$[?@.a\r<=@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after <=",+ "selector": "$[?@.a<= @.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after <=",+ "selector": "$[?@.a<=\n@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after <=",+ "selector": "$[?@.a<=\t@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after <=",+ "selector": "$[?@.a<=\r@.b]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space before >=",+ "selector": "$[?@.b >=@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline before >=",+ "selector": "$[?@.b\n>=@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab before >=",+ "selector": "$[?@.b\t>=@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return before >=",+ "selector": "$[?@.b\r>=@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space after >=",+ "selector": "$[?@.b>= @.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline after >=",+ "selector": "$[?@.b>=\n@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab after >=",+ "selector": "$[?@.b>=\t@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return after >=",+ "selector": "$[?@.b>=\r@.a]",+ "document": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ },+ {+ "a": 2,+ "b": 1+ }+ ],+ "result": [+ {+ "a": 1,+ "b": 1+ },+ {+ "a": 1,+ "b": 2+ }+ ],+ "result_paths": [+ "$[0]",+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space between logical not and test expression",+ "selector": "$[?! @.a]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline between logical not and test expression",+ "selector": "$[?!\n@.a]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab between logical not and test expression",+ "selector": "$[?!\t@.a]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return between logical not and test expression",+ "selector": "$[?!\r@.a]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "d": "f"+ }+ ],+ "result_paths": [+ "$[1]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, space between logical not and parenthesized expression",+ "selector": "$[?! (@.a=='b')]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, newline between logical not and parenthesized expression",+ "selector": "$[?!\n(@.a=='b')]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, tab between logical not and parenthesized expression",+ "selector": "$[?!\t(@.a=='b')]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, operators, return between logical not and parenthesized expression",+ "selector": "$[?!\r(@.a=='b')]",+ "document": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "b",+ "d": "f"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result": [+ {+ "a": "a",+ "d": "e"+ },+ {+ "a": "d",+ "d": "f"+ }+ ],+ "result_paths": [+ "$[0]",+ "$[2]"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between root and bracket",+ "selector": "$ ['a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between root and bracket",+ "selector": "$\n['a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between root and bracket",+ "selector": "$\t['a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between root and bracket",+ "selector": "$\r['a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between bracket and bracket",+ "selector": "$['a'] ['b']",+ "document": {+ "a": {+ "b": "ab"+ }+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between bracket and bracket",+ "selector": "$['a'] \n['b']",+ "document": {+ "a": {+ "b": "ab"+ }+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between bracket and bracket",+ "selector": "$['a'] \t['b']",+ "document": {+ "a": {+ "b": "ab"+ }+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between bracket and bracket",+ "selector": "$['a'] \r['b']",+ "document": {+ "a": {+ "b": "ab"+ }+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between root and dot",+ "selector": "$ .a",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between root and dot",+ "selector": "$\n.a",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between root and dot",+ "selector": "$\t.a",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between root and dot",+ "selector": "$\r.a",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between dot and name",+ "selector": "$. a",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between dot and name",+ "selector": "$.\na",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between dot and name",+ "selector": "$.\ta",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between dot and name",+ "selector": "$.\ra",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between recursive descent and name",+ "selector": "$.. a",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between recursive descent and name",+ "selector": "$..\na",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between recursive descent and name",+ "selector": "$..\ta",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between recursive descent and name",+ "selector": "$..\ra",+ "invalid_selector": true,+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between bracket and selector",+ "selector": "$[ 'a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between bracket and selector",+ "selector": "$[\n'a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between bracket and selector",+ "selector": "$[\t'a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between bracket and selector",+ "selector": "$[\r'a']",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between selector and bracket",+ "selector": "$['a' ]",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between selector and bracket",+ "selector": "$['a'\n]",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between selector and bracket",+ "selector": "$['a'\t]",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between selector and bracket",+ "selector": "$['a'\r]",+ "document": {+ "a": "ab"+ },+ "result": [+ "ab"+ ],+ "result_paths": [+ "$['a']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between selector and comma",+ "selector": "$['a' ,'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between selector and comma",+ "selector": "$['a'\n,'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between selector and comma",+ "selector": "$['a'\t,'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between selector and comma",+ "selector": "$['a'\r,'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, space between comma and selector",+ "selector": "$['a', 'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, newline between comma and selector",+ "selector": "$['a',\n'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, tab between comma and selector",+ "selector": "$['a',\t'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, selectors, return between comma and selector",+ "selector": "$['a',\r'b']",+ "document": {+ "a": "ab",+ "b": "bc"+ },+ "result": [+ "ab",+ "bc"+ ],+ "result_paths": [+ "$['a']",+ "$['b']"+ ],+ "tags": [+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, space between start and colon",+ "selector": "$[1 :5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, newline between start and colon",+ "selector": "$[1\n:5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, tab between start and colon",+ "selector": "$[1\t:5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, return between start and colon",+ "selector": "$[1\r:5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, space between colon and end",+ "selector": "$[1: 5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, newline between colon and end",+ "selector": "$[1:\n5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, tab between colon and end",+ "selector": "$[1:\t5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, return between colon and end",+ "selector": "$[1:\r5:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, space between end and colon",+ "selector": "$[1:5 :2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, newline between end and colon",+ "selector": "$[1:5\n:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, tab between end and colon",+ "selector": "$[1:5\t:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, return between end and colon",+ "selector": "$[1:5\r:2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, space between colon and step",+ "selector": "$[1:5: 2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, newline between colon and step",+ "selector": "$[1:5:\n2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, tab between colon and step",+ "selector": "$[1:5:\t2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ },+ {+ "name": "whitespace, slice, return between colon and step",+ "selector": "$[1:5:\r2]",+ "document": [+ 1,+ 2,+ 3,+ 4,+ 5,+ 6+ ],+ "result": [+ 2,+ 4+ ],+ "result_paths": [+ "$[1]",+ "$[3]"+ ],+ "tags": [+ "index",+ "whitespace"+ ]+ }+ ]+}
src/Data/Aeson/JSONPath.hs view
@@ -27,15 +27,16 @@ import qualified Text.ParserCombinators.Parsec as P -import Data.Aeson (Value)-import Data.Vector (Vector)-import Language.Haskell.TH.Quote (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (lift)+import Data.Aeson (Value)+import Data.Vector (Vector)+import Language.Haskell.TH.Quote (QuasiQuoter (..))+import Language.Haskell.TH.Syntax (lift) -import Data.Aeson.JSONPath.Query.Types (Query (..))-import Data.Aeson.JSONPath.Query (Queryable (..))-import Data.Aeson.JSONPath.Parser (pQuery)+import Data.Aeson.JSONPath.Parser (pQuery)+import Data.Aeson.JSONPath.Query (qQuery, qQueryLocated) +import Data.Aeson.JSONPath.Types+ import Prelude -- |@@ -85,7 +86,11 @@ -- artist = queryQQ [jsonPath|$.art[ist|] json -- fails at compilation time -- @ queryQQ :: Query -> Value -> Vector Value-queryQQ q root = query' q root root+queryQQ q root = qQuery q QueryState {+ rootVal = root+ , curVal = root+ , executeQuery = qQuery+} -- | -- Get the location of the returned nodes along with the node@@ -110,7 +115,11 @@ -- ("$[\'title\']",String "Space Oddity")] -- @ queryLocatedQQ :: Query -> Value -> Vector (String, Value)-queryLocatedQQ q root = queryLocated' q root root "$"+queryLocatedQQ q root = qQueryLocated q QueryState {+ rootVal = root+ , curVal = root+ , executeQuery = qQuery+} "$" -- $use --
src/Data/Aeson/JSONPath/Parser.hs view
@@ -1,375 +1,26 @@ {-# OPTIONS_GHC -Wno-unused-do-bind #-} {- | Module : Data.Aeson.JSONPath.Parser-Description : Parses the raw query to ADT+Description : JSONPath Query Parser Copyright : (c) 2024-2025 Taimoor Zaeem License : MIT Maintainer : Taimoor Zaeem <mtaimoorzaeem@gmail.com> Stability : Experimental Portability : Portable -Parses raw query to Haskell Algebraic Data Types+This module is responsible for parsing the JSONPath query -} module Data.Aeson.JSONPath.Parser ( pQuery ) where -import qualified Data.Text as T import qualified Text.ParserCombinators.Parsec as P -import Data.Functor (($>))-import Data.Char (ord, chr)-import Data.Maybe (isNothing, fromMaybe)-import Data.Scientific (Scientific, scientific)-import GHC.Num (integerFromInt, integerToInt)-import Text.ParserCombinators.Parsec ((<|>))--import Data.Aeson.JSONPath.Query.Types+import Data.Aeson.JSONPath.Parser.Query (pRootQuery)+import Data.Aeson.JSONPath.Types import Prelude -- | Query parser pQuery :: P.Parser Query-pQuery = P.try pRootQuery <* P.eof--pRootQuery :: P.Parser Query-pRootQuery = do- P.char '$'- segs <- P.many (pSpaces *> pQuerySegment)- return $ Query { queryType = Root, querySegments = segs }--pCurrentQuery :: P.Parser Query-pCurrentQuery = do- P.char '@'- segs <- P.many pQuerySegment- return $ Query { queryType = Current, querySegments = segs }---pQuerySegment :: P.Parser QuerySegment-pQuerySegment = do- dotdot <- P.optionMaybe (P.try $ P.string "..")- seg <- pSegment $ isNothing dotdot- let segType = if isNothing dotdot then Child else Descendant- return $ QuerySegment { segmentType = segType, segment = seg }--pSegment :: Bool -> P.Parser Segment-pSegment isChild = P.try pBracketed- <|> P.try (pDotted isChild)- <|> P.try (pWildcardSeg isChild)---pBracketed :: P.Parser Segment-pBracketed = do- P.char '['- pSpaces- sel <- pSelector- optionalSels <- P.many pCommaSepSelectors- pSpaces- P.char ']'- return $ Bracketed (sel:optionalSels)- where- pCommaSepSelectors :: P.Parser Selector- pCommaSepSelectors = P.try $ pSpaces *> P.char ',' *> pSpaces *> pSelector---pDotted :: Bool -> P.Parser Segment-pDotted isChild = do- (if isChild then P.string "." else P.string "")- P.lookAhead (P.letter <|> P.oneOf "_" <|> pUnicodeChar)- key <- T.pack <$> P.many1 (P.alphaNum <|> P.oneOf "_" <|> pUnicodeChar)- return $ Dotted key---pWildcardSeg :: Bool -> P.Parser Segment-pWildcardSeg isChild = (if isChild then P.string "." else P.string "") *> P.char '*' $> WildcardSegment- -pSelector :: P.Parser Selector-pSelector = P.try pName- <|> P.try pSlice - <|> P.try pIndex- <|> P.try pWildcardSel- <|> P.try pFilter--pName :: P.Parser Selector-pName = Name . T.pack <$> (P.try pSingleQuotted <|> P.try pDoubleQuotted)--pIndex :: P.Parser Selector-pIndex = Index <$> pSignedInt--pSlice :: P.Parser Selector-pSlice = do- start <- P.optionMaybe (pSignedInt <* pSpaces)- P.char ':'- pSpaces- end <- P.optionMaybe (pSignedInt <* pSpaces)- step <- P.optionMaybe (P.char ':' *> P.optionMaybe (pSpaces *> pSignedInt))- return $ ArraySlice (start, end, case step of- Just (Just n) -> n- _ -> 1)---pWildcardSel :: P.Parser Selector-pWildcardSel = P.char '*' $> WildcardSelector---pFilter :: P.Parser Selector-pFilter = do- P.char '?'- pSpaces- Filter <$> pLogicalOrExpr---pLogicalOrExpr :: P.Parser LogicalOrExpr-pLogicalOrExpr = do- expr <- pLogicalAndExpr- optionalExprs <- P.many pOrSepLogicalAndExprs- return $ LogicalOr (expr:optionalExprs)- where- pOrSepLogicalAndExprs :: P.Parser LogicalAndExpr- pOrSepLogicalAndExprs = P.try $ pSpaces *> P.string "||" *> pSpaces *> pLogicalAndExpr--pLogicalAndExpr :: P.Parser LogicalAndExpr-pLogicalAndExpr = do- expr <- pBasicExpr- optionalExprs <- P.many pAndSepBasicExprs- return $ LogicalAnd (expr:optionalExprs)- where- pAndSepBasicExprs :: P.Parser BasicExpr- pAndSepBasicExprs = P.try $ pSpaces *> P.string "&&" *> pSpaces *> pBasicExpr--pBasicExpr :: P.Parser BasicExpr-pBasicExpr = P.try pParenExpr- <|> P.try pComparisonExpr- <|> P.try pTestExpr--pParenExpr :: P.Parser BasicExpr-pParenExpr = do- notOp <- P.optionMaybe (P.char '!' <* pSpaces)- P.char '('- pSpaces- expr <- pLogicalOrExpr- pSpaces- P.char ')'- let parenExp = if isNothing notOp then Paren expr else NotParen expr- return parenExp--pTestExpr :: P.Parser BasicExpr-pTestExpr = do- notOp <- P.optionMaybe (P.char '!' <* pSpaces)- q <- P.try pRootQuery <|> P.try pCurrentQuery- let testExp = if isNothing notOp then Test q else NotTest q- return testExp--pComparisonExpr :: P.Parser BasicExpr-pComparisonExpr = do- leftC <- pComparable- pSpaces- compOp <- pComparisonOp- pSpaces- Comparison . Comp leftC compOp <$> pComparable--pComparisonOp :: P.Parser ComparisonOp-pComparisonOp = P.try (P.string ">=" $> GreaterOrEqual)- <|> P.try (P.string "<=" $> LessOrEqual)- <|> P.try (P.char '>' $> Greater)- <|> P.try (P.char '<' $> Less)- <|> P.try (P.string "!=" $> NotEqual)- <|> P.try (P.string "==" $> Equal)--pComparable :: P.Parser Comparable-pComparable = P.try pCompLitString- <|> P.try pCompLitNum- <|> P.try pCompLitBool- <|> P.try pCompLitNull- <|> P.try pCompSQ--pCompLitString :: P.Parser Comparable-pCompLitString = CompLitString . T.pack <$> (P.try pSingleQuotted <|> P.try pDoubleQuotted)--pCompLitNum :: P.Parser Comparable-pCompLitNum = CompLitNum - <$> (P.try (P.string "-0" $> (0 :: Scientific)) -- edge case- <|> P.try pDoubleScientific - <|> P.try pScientific)--pCompLitBool :: P.Parser Comparable-pCompLitBool = CompLitBool <$> (P.try (P.string "true" $> True) <|> P.try (P.string "false" $> False))--pCompLitNull :: P.Parser Comparable-pCompLitNull = P.string "null" $> CompLitNull--pCompSQ :: P.Parser Comparable-pCompSQ = CompSQ <$> (P.try pCurrentSingleQ <|> P.try pRootSingleQ)--pCurrentSingleQ :: P.Parser SingularQuery-pCurrentSingleQ = do- P.char '@'- segs <- P.many pSingularQuerySegment- return $ SingularQuery { singularQueryType = CurrentSQ, singularQuerySegments = segs }--pRootSingleQ :: P.Parser SingularQuery-pRootSingleQ = do- P.char '$'- segs <- P.many pSingularQuerySegment- return $ SingularQuery { singularQueryType = RootSQ, singularQuerySegments = segs }--pSingularQuerySegment :: P.Parser SingularQuerySegment-pSingularQuerySegment = P.try pSingularQNameSeg <|> P.try pSingularQIndexSeg--pSingularQNameSeg :: P.Parser SingularQuerySegment-pSingularQNameSeg = P.try pSingularQNameBracketed <|> P.try pSingularQNameDotted- where- pSingularQNameBracketed = do- P.char '['- name <- T.pack <$> (P.try pSingleQuotted <|> P.try pDoubleQuotted)- P.char ']'- return $ NameSQSeg name-- pSingularQNameDotted = do- P.char '.'- P.lookAhead (P.letter <|> P.oneOf "_" <|> pUnicodeChar)- name <- T.pack <$> P.many1 (P.alphaNum <|> P.oneOf "_" <|> pUnicodeChar)- return $ NameSQSeg name--pSingularQIndexSeg :: P.Parser SingularQuerySegment-pSingularQIndexSeg = do- P.char '['- idx <- pSignedInt- P.char ']'- return $ IndexSQSeg idx--pSignedInt :: P.Parser Int-pSignedInt = do- P.notFollowedBy (P.string "-0" *> P.optional P.digit) -- no leading -011... etc- P.notFollowedBy (P.char '0' *> P.digit) -- no leading 011... etc- sign <- P.optionMaybe $ P.char '-'- num <- (read <$> P.many1 P.digit) :: P.Parser Integer- checkNumOutOfRange num sign- where- minInt = -9007199254740991- maxInt = 9007199254740991- checkNumOutOfRange num (Just _) =- if -num < minInt then fail "out of range"- else return $ integerToInt (-num)-- checkNumOutOfRange num Nothing =- if num > maxInt then fail "out of range"- else return $ integerToInt num---- TODO: Fix Double parse error "1.12e+23"-pScientific :: P.Parser Scientific-pScientific = do- mantissa <- pSignedInt- expo <- P.optionMaybe (P.oneOf "eE" *> pExponent)- return $ scientific (integerFromInt mantissa) (fromMaybe 0 expo)--pDoubleScientific :: P.Parser Scientific-pDoubleScientific = do- whole <- P.many1 P.digit- P.char '.'- frac <- P.many1 P.digit- expo <- P.optionMaybe (P.oneOf "eE" *> pExponent)- let num = read (whole ++ "." ++ frac ++ maybe "" (\x -> "e" ++ show x) expo) :: Scientific- return num--pExponent :: P.Parser Int-pExponent = do- sign <- P.optionMaybe (P.oneOf "+-")- num <- read <$> P.many1 P.digit- return $ case sign of- Just '-' -> -num- _ -> num--pUnicodeChar :: P.Parser Char-pUnicodeChar = P.satisfy inRange- where- inRange c = let code = ord c in- (code >= 0x80 && code <= 0xD7FF) ||- (code >= 0xE000 && code <= 0x10FFFF)---- https://www.rfc-editor.org/rfc/rfc9535#name-syntax-pSpaces :: P.Parser [Char]-pSpaces = P.many (P.oneOf " \n\r\t")--pSingleQuotted :: P.Parser String-pSingleQuotted = P.char '\'' *> P.many inQuote <* P.char '\''- where- inQuote = P.try pUnescaped- <|> P.try (P.char '\"')- <|> P.try (P.string "\\\'" $> '\'')- <|> P.try pEscaped--pDoubleQuotted :: P.Parser String-pDoubleQuotted = P.char '\"' *> P.many inQuote <* P.char '\"'- where- inQuote = P.try pUnescaped- <|> P.try (P.char '\'')- <|> P.try (P.string "\\\"" $> '\"')- <|> P.try pEscaped--pUnescaped :: P.Parser Char-pUnescaped = P.satisfy inRange- where- inRange c = let code = ord c in- (code >= 0x20 && code <= 0x21) ||- (code >= 0x23 && code <= 0x26) ||- (code >= 0x28 && code <= 0x5B) ||- (code >= 0x5D && code <= 0xD7FF) ||- (code >= 0xE000 && code <= 0x10FFFF)--pEscaped :: P.Parser Char-pEscaped = do- P.char '\\'- P.try pEscapees <|> P.try pHexUnicode- where- pEscapees = P.try (P.char 'b' $> '\b')- <|> P.try (P.char 'f' $> '\f')- <|> P.try (P.char 'n' $> '\n')- <|> P.try (P.char 'r' $> '\r')- <|> P.try (P.char 't' $> '\t')- <|> P.try (P.char '/')- <|> P.try (P.char '\\')--pHexUnicode :: P.Parser Char-pHexUnicode = P.try pNonSurrogate <|> P.try pSurrogatePair- where- pNonSurrogate = P.try pNonSurrogateFirst <|> P.try pNonSurrogateSecond- where- pNonSurrogateFirst = do- P.char 'u'- c1 <- P.digit <|> P.oneOf "AaBbCcEeFf"- c2 <- P.hexDigit- c3 <- P.hexDigit- c4 <- P.hexDigit- return $ chr (read ("0x" ++ [c1,c2,c3,c4]) :: Int)-- pNonSurrogateSecond = do- P.char 'u'- c1 <- P.oneOf "Dd"- c2 <- P.oneOf "01234567"- c3 <- P.hexDigit- c4 <- P.hexDigit- return $ chr (read ("0x" ++ [c1,c2,c3,c4]) :: Int)-- pSurrogatePair = do- P.char 'u'- high <- pHighSurrogate- P.char '\\'- P.char 'u'- fromHighAndLow high <$> pLowSurrogate- where- pHighSurrogate = do- c1 <- P.oneOf "Dd"- c2 <- P.oneOf "89AaBb"- c3 <- P.hexDigit- c4 <- P.hexDigit- return (read ("0x" ++ [c1,c2,c3,c4]) :: Int)-- pLowSurrogate = do- c1 <- P.oneOf "Dd"- c2 <- P.oneOf "CcDdEeFf"- c3 <- P.hexDigit- c4 <- P.hexDigit- return (read ("0x" ++ [c1,c2,c3,c4]) :: Int)- - fromHighAndLow hi lo = chr $ ((hi - 0xD800) * 0x400) + (lo - 0xDC00) + 0x10000+pQuery = pRootQuery <* P.eof
+ src/Data/Aeson/JSONPath/Parser/Common.hs view
@@ -0,0 +1,21 @@+module Data.Aeson.JSONPath.Parser.Common+ ( pSpaces+ , pUnicodeChar+ )+ where++import qualified Text.ParserCombinators.Parsec as P+import Data.Char (ord)++import Prelude++-- https://www.rfc-editor.org/rfc/rfc9535#name-syntax+pSpaces :: P.Parser [Char]+pSpaces = P.many (P.oneOf " \n\r\t")++pUnicodeChar :: P.Parser Char+pUnicodeChar = P.satisfy inRange+ where+ inRange c = let code = ord c in+ (code >= 0x80 && code <= 0xD7FF) ||+ (code >= 0xE000 && code <= 0x10FFFF)
+ src/Data/Aeson/JSONPath/Parser/Filter.hs view
@@ -0,0 +1,150 @@+{-# OPTIONS_GHC -Wno-unused-do-bind #-}+module Data.Aeson.JSONPath.Parser.Filter+ ( pFilter )+ where++import qualified Data.Text as T+import qualified Text.ParserCombinators.Parsec as P++import Data.Functor (($>))+import Data.Maybe (isNothing)+import Data.Scientific (Scientific)+import Text.ParserCombinators.Parsec ((<|>))++import Data.Aeson.JSONPath.Parser.Name+import Data.Aeson.JSONPath.Parser.Number+import Data.Aeson.JSONPath.Parser.Common++import Data.Aeson.JSONPath.Types++import Prelude++pFilter :: P.Parser a -> P.Parser (Selector a)+pFilter pQ = do+ P.char '?'+ pSpaces+ Filter <$> pLogicalOrExpr pQ+++pLogicalOrExpr :: P.Parser a -> P.Parser (LogicalOrExpr a)+pLogicalOrExpr pQ = do+ expr <- pLogicalAndExpr pQ+ optionalExprs <- P.many $ pOrSepLogicalAndExprs pQ+ return $ LogicalOr (expr:optionalExprs)+ where+ pOrSepLogicalAndExprs :: P.Parser a -> P.Parser (LogicalAndExpr a)+ pOrSepLogicalAndExprs pQ' = P.try $ pSpaces *> P.string "||" *> pSpaces *> pLogicalAndExpr pQ'++pLogicalAndExpr :: P.Parser a -> P.Parser (LogicalAndExpr a)+pLogicalAndExpr pQ = do+ expr <- pBasicExpr pQ+ optionalExprs <- P.many $ pAndSepBasicExprs pQ+ return $ LogicalAnd (expr:optionalExprs)+ where+ pAndSepBasicExprs :: P.Parser a -> P.Parser (BasicExpr a)+ pAndSepBasicExprs pQ' = P.try $ pSpaces *> P.string "&&" *> pSpaces *> pBasicExpr pQ'++pBasicExpr :: P.Parser a -> P.Parser (BasicExpr a)+pBasicExpr pQ + = P.try (pParenExpr pQ)+ <|> P.try pComparisonExpr+ <|> P.try (pTestExpr pQ)++pParenExpr :: P.Parser a -> P.Parser (BasicExpr a)+pParenExpr pQ = do+ notOp <- P.optionMaybe (P.char '!' <* pSpaces)+ P.char '('+ pSpaces+ expr <- pLogicalOrExpr pQ+ pSpaces+ P.char ')'+ let parenExp = if isNothing notOp then Paren expr else NotParen expr+ return parenExp++pTestExpr :: P.Parser a -> P.Parser (BasicExpr a)+pTestExpr pQ = do+ notOp <- P.optionMaybe (P.char '!' <* pSpaces)+ q <- P.try (FilterQuery <$> pQ)+ let testExp = if isNothing notOp then Test q else NotTest q+ return testExp++pComparisonExpr :: P.Parser (BasicExpr a)+pComparisonExpr = do+ leftC <- pComparable+ pSpaces+ compOp <- pComparisonOp+ pSpaces+ Comparison . Comp leftC compOp <$> pComparable++pComparisonOp :: P.Parser ComparisonOp+pComparisonOp = P.try (P.string ">=" $> GreaterOrEqual)+ <|> P.try (P.string "<=" $> LessOrEqual)+ <|> P.try (P.char '>' $> Greater)+ <|> P.try (P.char '<' $> Less)+ <|> P.try (P.string "!=" $> NotEqual)+ <|> P.try (P.string "==" $> Equal)++pComparable :: P.Parser Comparable+pComparable = P.try pCompLit <|> P.try pCompSQ++pCompLit :: P.Parser Comparable+pCompLit = CompLit+ <$> (P.try pLitString+ <|> P.try pLitNum+ <|> P.try pLitBool+ <|> P.try pLitNull)++pLitString :: P.Parser Literal+pLitString = LitString . T.pack <$> (P.try pSingleQuotted <|> P.try pDoubleQuotted)++pLitNum :: P.Parser Literal+pLitNum = LitNum + <$> (P.try (P.string "-0" $> (0 :: Scientific)) -- edge case+ <|> P.try pDoubleScientific + <|> P.try pScientific)++pLitBool :: P.Parser Literal+pLitBool = LitBool <$> (P.try (P.string "true" $> True) <|> P.try (P.string "false" $> False))++pLitNull :: P.Parser Literal+pLitNull = P.string "null" $> LitNull++pCompSQ :: P.Parser Comparable+pCompSQ = CompSQ <$> (P.try pCurrentSingleQ <|> P.try pRootSingleQ)++pCurrentSingleQ :: P.Parser SingularQuery+pCurrentSingleQ = do+ P.char '@'+ segs <- P.many $ P.try (pSpaces *> pSingularQuerySegment)+ return $ SingularQuery { singularQueryType = CurrentSQ, singularQuerySegments = segs }++pRootSingleQ :: P.Parser SingularQuery+pRootSingleQ = do+ P.char '$'+ segs <- P.many $ P.try (pSpaces *> pSingularQuerySegment)+ return $ SingularQuery { singularQueryType = RootSQ, singularQuerySegments = segs }++pSingularQuerySegment :: P.Parser SingularQuerySegment+pSingularQuerySegment = P.try pSingularQNameSeg <|> P.try pSingularQIndexSeg++pSingularQNameSeg :: P.Parser SingularQuerySegment+pSingularQNameSeg = P.try pSingularQNameBracketed <|> P.try pSingularQNameDotted+ where+ pSingularQNameBracketed = do+ P.char '['+ name <- T.pack <$> (P.try pSingleQuotted <|> P.try pDoubleQuotted)+ P.char ']'+ return $ NameSQSeg name++ pSingularQNameDotted = do+ P.char '.'+ P.lookAhead (P.letter <|> P.oneOf "_" <|> pUnicodeChar)+ name <- T.pack <$> P.many1 (P.alphaNum <|> P.oneOf "_" <|> pUnicodeChar)+ return $ NameSQSeg name++pSingularQIndexSeg :: P.Parser SingularQuerySegment+pSingularQIndexSeg = do+ P.char '['+ idx <- pSignedInt+ P.char ']'+ return $ IndexSQSeg idx
+ src/Data/Aeson/JSONPath/Parser/Name.hs view
@@ -0,0 +1,97 @@+{-# OPTIONS_GHC -Wno-unused-do-bind #-}+module Data.Aeson.JSONPath.Parser.Name+ ( pSingleQuotted+ , pDoubleQuotted+ )+ where++import qualified Text.ParserCombinators.Parsec as P++import Data.Functor (($>))+import Data.Char (ord, chr)+import Text.ParserCombinators.Parsec ((<|>))++import Prelude++pSingleQuotted :: P.Parser String+pSingleQuotted = P.char '\'' *> P.many inQuote <* P.char '\''+ where+ inQuote = P.try pUnescaped+ <|> P.try (P.char '\"')+ <|> P.try (P.string "\\\'" $> '\'')+ <|> P.try pEscaped++pDoubleQuotted :: P.Parser String+pDoubleQuotted = P.char '\"' *> P.many inQuote <* P.char '\"'+ where+ inQuote = P.try pUnescaped+ <|> P.try (P.char '\'')+ <|> P.try (P.string "\\\"" $> '\"')+ <|> P.try pEscaped++pUnescaped :: P.Parser Char+pUnescaped = P.satisfy inRange+ where+ inRange c = let code = ord c in+ (code >= 0x20 && code <= 0x21) ||+ (code >= 0x23 && code <= 0x26) ||+ (code >= 0x28 && code <= 0x5B) ||+ (code >= 0x5D && code <= 0xD7FF) ||+ (code >= 0xE000 && code <= 0x10FFFF)++pEscaped :: P.Parser Char+pEscaped = do+ P.char '\\'+ P.try pEscapees <|> P.try pHexUnicode+ where+ pEscapees = P.try (P.char 'b' $> '\b')+ <|> P.try (P.char 'f' $> '\f')+ <|> P.try (P.char 'n' $> '\n')+ <|> P.try (P.char 'r' $> '\r')+ <|> P.try (P.char 't' $> '\t')+ <|> P.try (P.char '/')+ <|> P.try (P.char '\\')++pHexUnicode :: P.Parser Char+pHexUnicode = P.try pNonSurrogate <|> P.try pSurrogatePair+ where+ pNonSurrogate = P.try pNonSurrogateFirst <|> P.try pNonSurrogateSecond+ where+ pNonSurrogateFirst = do+ P.char 'u'+ c1 <- P.digit <|> P.oneOf "AaBbCcEeFf"+ c2 <- P.hexDigit+ c3 <- P.hexDigit+ c4 <- P.hexDigit+ return $ chr (read ("0x" ++ [c1,c2,c3,c4]) :: Int)++ pNonSurrogateSecond = do+ P.char 'u'+ c1 <- P.oneOf "Dd"+ c2 <- P.oneOf "01234567"+ c3 <- P.hexDigit+ c4 <- P.hexDigit+ return $ chr (read ("0x" ++ [c1,c2,c3,c4]) :: Int)++ pSurrogatePair = do+ P.char 'u'+ high <- pHighSurrogate+ P.char '\\'+ P.char 'u'+ fromHighAndLow high <$> pLowSurrogate+ where+ pHighSurrogate = do+ c1 <- P.oneOf "Dd"+ c2 <- P.oneOf "89AaBb"+ c3 <- P.hexDigit+ c4 <- P.hexDigit+ return (read ("0x" ++ [c1,c2,c3,c4]) :: Int)++ pLowSurrogate = do+ c1 <- P.oneOf "Dd"+ c2 <- P.oneOf "CcDdEeFf"+ c3 <- P.hexDigit+ c4 <- P.hexDigit+ return (read ("0x" ++ [c1,c2,c3,c4]) :: Int)++ fromHighAndLow hi lo = chr $ ((hi - 0xD800) * 0x400) + (lo - 0xDC00) + 0x10000
+ src/Data/Aeson/JSONPath/Parser/Number.hs view
@@ -0,0 +1,57 @@+{-# OPTIONS_GHC -Wno-unused-do-bind #-}+module Data.Aeson.JSONPath.Parser.Number+ ( pSignedInt+ , pScientific+ , pDoubleScientific+ )+ where++import qualified Text.ParserCombinators.Parsec as P++import Data.Maybe (fromMaybe)+import Data.Scientific (Scientific, scientific)+import GHC.Num (integerFromInt, integerToInt)++import Prelude++pSignedInt :: P.Parser Int+pSignedInt = do+ P.notFollowedBy (P.string "-0" *> P.optional P.digit) -- no leading -011... etc+ P.notFollowedBy (P.char '0' *> P.digit) -- no leading 011... etc+ sign <- P.optionMaybe $ P.char '-'+ num <- (read <$> P.many1 P.digit) :: P.Parser Integer+ checkNumOutOfRange num sign+ where+ minInt = -9007199254740991+ maxInt = 9007199254740991+ checkNumOutOfRange num (Just _) =+ if -num < minInt then fail "out of range"+ else return $ integerToInt (-num)++ checkNumOutOfRange num Nothing =+ if num > maxInt then fail "out of range"+ else return $ integerToInt num++-- TODO: Fix Double parse error "1.12e+23"+pScientific :: P.Parser Scientific+pScientific = do+ mantissa <- pSignedInt+ expo <- P.optionMaybe (P.oneOf "eE" *> pExponent)+ return $ scientific (integerFromInt mantissa) (fromMaybe 0 expo)++pDoubleScientific :: P.Parser Scientific+pDoubleScientific = do+ whole <- P.many1 P.digit+ P.char '.'+ frac <- P.many1 P.digit+ expo <- P.optionMaybe (P.oneOf "eE" *> pExponent)+ let num = read (whole ++ "." ++ frac ++ maybe "" (\x -> "e" ++ show x) expo) :: Scientific+ return num++pExponent :: P.Parser Int+pExponent = do+ sign <- P.optionMaybe (P.oneOf "+-")+ num <- read <$> P.many1 P.digit+ return $ case sign of+ Just '-' -> -num+ _ -> num
+ src/Data/Aeson/JSONPath/Parser/Query.hs view
@@ -0,0 +1,105 @@+{-# OPTIONS_GHC -Wno-unused-do-bind #-}+module Data.Aeson.JSONPath.Parser.Query+ ( pRootQuery+ , pCurrentQuery )+ where++import qualified Data.Text as T+import qualified Text.ParserCombinators.Parsec as P++import Data.Functor (($>))+import Data.Maybe (isNothing)+import Text.ParserCombinators.Parsec ((<|>))++import Data.Aeson.JSONPath.Parser.Filter (pFilter)+import Data.Aeson.JSONPath.Parser.Name+import Data.Aeson.JSONPath.Parser.Number+import Data.Aeson.JSONPath.Parser.Common+import Data.Aeson.JSONPath.Types++import Prelude++pRootQuery :: P.Parser Query+pRootQuery = do+ P.char '$'+ segs <- P.many $ P.try pSpacedOutSegments+ return $ Query { queryType = Root, querySegments = segs }+ where+ pQ = P.try pRootQuery <|> P.try pCurrentQuery+ pSpacedOutSegments = pSpaces *> pQuerySegment pQ++pCurrentQuery :: P.Parser Query+pCurrentQuery = do+ P.char '@'+ segs <- P.many $ P.try pSpacedOutSegments+ return $ Query { queryType = Current, querySegments = segs }+ where+ pQ = P.try pRootQuery <|> P.try pCurrentQuery+ pSpacedOutSegments = pSpaces *> pQuerySegment pQ+++pQuerySegment :: P.Parser a -> P.Parser (QuerySegment a)+pQuerySegment pQ = do+ dotdot <- P.optionMaybe (P.try $ P.string "..")+ seg <- pSegment pQ $ isNothing dotdot+ let segType = if isNothing dotdot then Child else Descendant+ return $ QuerySegment { segmentType = segType, segment = seg }++pSegment :: P.Parser a -> Bool -> P.Parser (Segment a)+pSegment pQ isChild+ = P.try (pBracketed pQ)+ <|> P.try (pDotted isChild)+ <|> P.try (pWildcardSeg isChild)++pBracketed :: P.Parser a -> P.Parser (Segment a)+pBracketed pQ = do+ P.char '['+ pSpaces+ sel <- pSelector pQ+ optionalSels <- P.many $ pCommaSepSelectors pQ+ pSpaces+ P.char ']'+ return $ Bracketed (sel:optionalSels)+ where+ pCommaSepSelectors :: P.Parser a -> P.Parser (Selector a)+ pCommaSepSelectors p = P.try $ pSpaces *> P.char ',' *> pSpaces *> pSelector p+++pDotted :: Bool -> P.Parser (Segment a)+pDotted isChild = do+ (if isChild then P.string "." else P.string "")+ P.lookAhead (P.letter <|> P.oneOf "_" <|> pUnicodeChar)+ key <- T.pack <$> P.many1 (P.alphaNum <|> P.oneOf "_" <|> pUnicodeChar)+ return $ Dotted key+++pWildcardSeg :: Bool -> P.Parser (Segment a)+pWildcardSeg isChild = (if isChild then P.string "." else P.string "") *> P.char '*' $> WildcardSegment+ +pSelector :: P.Parser a -> P.Parser (Selector a)+pSelector pQ = P.try pName+ <|> P.try pSlice + <|> P.try pIndex+ <|> P.try pWildcardSel+ <|> P.try (pFilter pQ)++pName :: P.Parser (Selector a)+pName = Name . T.pack <$> (P.try pSingleQuotted <|> P.try pDoubleQuotted)++pIndex :: P.Parser (Selector a)+pIndex = Index <$> pSignedInt++pSlice :: P.Parser (Selector a)+pSlice = do+ start <- P.optionMaybe (pSignedInt <* pSpaces)+ P.char ':'+ pSpaces+ end <- P.optionMaybe (pSignedInt <* pSpaces)+ step <- P.optionMaybe (P.char ':' *> P.optionMaybe (pSpaces *> pSignedInt))+ return $ ArraySlice (start, end, case step of+ Just (Just n) -> n+ _ -> 1)+++pWildcardSel :: P.Parser (Selector a)+pWildcardSel = P.char '*' $> WildcardSelector
src/Data/Aeson/JSONPath/Query.hs view
@@ -1,290 +1,18 @@-{-# LANGUAGE RecordWildCards #-} {- | Module : Data.Aeson.JSONPath.Query-Description : Algorithm for query runner+Description : Execute JSONPath Query after parsing Copyright : (c) 2024-2025 Taimoor Zaeem License : MIT Maintainer : Taimoor Zaeem <mtaimoorzaeem@gmail.com> Stability : Experimental Portability : Portable -This module contains core functions that runs the query on 'Value'.+This module is responsible for executing the JSONPath query -} module Data.Aeson.JSONPath.Query- ( Queryable (..) )+ (+ module Data.Aeson.JSONPath.Query.Query+ ) where -import Control.Monad (join)-import Data.Aeson (Value)-import Data.Vector (Vector)--import qualified Data.Aeson as JSON-import qualified Data.Aeson.KeyMap as KM-import qualified Data.Aeson.Key as K-import qualified Data.Text as T-import qualified Data.Vector as V--import Data.Aeson.JSONPath.Query.Types--import Prelude---- |-class Queryable a where- query' :: a -> Value -> Value -> Vector Value- queryLocated' :: a -> Value -> Value -> String -> Vector (String,Value)--instance Queryable Query where- query' = qQuery- queryLocated' = qQueryLocated--instance Queryable QuerySegment where- query' = qQuerySegment- queryLocated' = qQuerySegmentLocated--instance Queryable Segment where- query' = qSegment- queryLocated' = qSegmentLocated--instance Queryable Selector where- query' = qSelector- queryLocated' = qSelectorLocated---- TODO: the whole module is kinda bloated, refactor--- Blockers with refactoring: qQuery is used recursively--qQuery :: Query -> Value -> Value -> Vector Value-qQuery Query{..} root current = case queryType of- Root -> foldl applySegment (V.singleton root) querySegments- Current -> foldl applySegment (V.singleton current) querySegments- where- applySegment :: Vector Value -> QuerySegment -> Vector Value- applySegment vec seg = join $ V.map (qQuerySegment seg root) vec--qQueryLocated :: Query -> Value -> Value -> String -> Vector (String,Value)-qQueryLocated Query{..} root current loc = case queryType of- Root -> foldl applySegment (V.singleton (loc,root)) querySegments- Current -> foldl applySegment (V.singleton (loc,current)) querySegments- where- applySegment :: Vector (String,Value) -> QuerySegment -> Vector (String,Value)- applySegment vec seg = join $ V.map (\(location,cur) -> qQuerySegmentLocated seg root cur location) vec--qQuerySegment :: QuerySegment -> Value -> Value -> Vector Value-qQuerySegment QuerySegment{..} root current = case segmentType of- Child -> joinAfterMap $ V.singleton current- Descendant -> joinAfterMap $ allElemsRecursive current- where- joinAfterMap x = join $ V.map (qSegment segment root) x--qQuerySegmentLocated :: QuerySegment -> Value -> Value -> String -> Vector (String, Value)-qQuerySegmentLocated QuerySegment{..} root current loc = case segmentType of- Child -> joinAfterMap $ V.singleton (loc,current)- Descendant -> joinAfterMap $ allElemsRecursiveLocated (loc,current)- where- joinAfterMap x = join $ V.map (\(location,cur) -> qSegmentLocated segment root cur location) x--qSegment :: Segment -> Value -> Value -> Vector Value-qSegment (Bracketed sels) root current = V.concat $ map (\sel -> qSelector sel root current) sels-qSegment (Dotted key) root current = qSelector (Name key) root current-qSegment WildcardSegment root current = qSelector WildcardSelector root current--qSegmentLocated :: Segment -> Value -> Value -> String -> Vector (String,Value)-qSegmentLocated (Bracketed sels) root current loc = V.concat $ map (\sel -> qSelectorLocated sel root current loc) sels-qSegmentLocated (Dotted key) root current loc = qSelectorLocated (Name key) root current loc-qSegmentLocated WildcardSegment root current loc = qSelectorLocated WildcardSelector root current loc----- TODO: Looks kinda ugly, make it pretty <3-allElemsRecursive :: Value -> Vector Value-allElemsRecursive o@(JSON.Object obj) = V.concat [- V.singleton o,- V.concat $ map allElemsRecursive (KM.elems obj)- ]-allElemsRecursive a@(JSON.Array arr) = V.concat [- V.singleton a,- V.concat $ map allElemsRecursive (V.toList arr)- ]-allElemsRecursive _ = V.empty---- TODO: Looks kinda ugly, make it pretty <3-allElemsRecursiveLocated :: (String,Value) -> Vector (String,Value)-allElemsRecursiveLocated (loc, o@(JSON.Object obj)) = V.concat [- V.singleton (loc,o),- V.concat $ zipWith (curry allElemsRecursiveLocated) (replicate (length (KM.elems obj)) loc) (KM.elems obj)- ]-allElemsRecursiveLocated (loc, a@(JSON.Array arr)) = V.concat [- V.singleton (loc,a),- V.concat $ zipWith (curry allElemsRecursiveLocated) (replicate (V.length arr) loc) (V.toList arr)- ]-allElemsRecursiveLocated _ = V.empty---qSelector :: Selector -> Value -> Value -> Vector Value-qSelector (Name key) _ (JSON.Object obj) = maybe V.empty V.singleton $ KM.lookup (K.fromText key) obj-qSelector (Name _) _ _ = V.empty-qSelector (Index idx) _ (JSON.Array arr) = maybe V.empty V.singleton $ if idx >= 0 then (V.!?) arr idx else (V.!?) arr (idx + V.length arr)-qSelector (Index _) _ _ = V.empty-qSelector (ArraySlice startEndStep) _ (JSON.Array arr) = sliceArray startEndStep arr-qSelector (ArraySlice _) _ _ = V.empty-qSelector (Filter orExpr) root current = filterOrExpr orExpr root current-qSelector WildcardSelector _ cur = case cur of- (JSON.Object obj) -> V.fromList $ KM.elems obj- (JSON.Array arr) -> arr- _ -> V.empty--qSelectorLocated :: Selector -> Value -> Value -> String -> Vector (String,Value)-qSelectorLocated (Name key) _ (JSON.Object obj) loc = maybe V.empty (\x-> V.singleton (loc ++ "['" ++ T.unpack key ++ "']", x)) $ KM.lookup (K.fromText key) obj-qSelectorLocated (Name _) _ _ _ = V.empty-qSelectorLocated (Index idx) _ (JSON.Array arr) loc = maybe V.empty (\x-> V.singleton (newLocation, x)) $ (V.!?) arr (getIndex idx)- where- newLocation = loc ++ "[" ++ show (getIndex idx) ++ "]"- getIndex i = if i >= 0 then i else i + V.length arr-qSelectorLocated (Index _) _ _ _ = V.empty-qSelectorLocated (ArraySlice (start,end,step)) _ (JSON.Array arr) loc = sliceArrayLocated (start,end,step) $ V.zip (V.fromList locs) arr- where- locs = [ loc ++ "[" ++ show i ++ "]" | i <- indices ]- indices = [0..(V.length arr - 1)]-qSelectorLocated (ArraySlice _) _ _ _ = V.empty-qSelectorLocated (Filter orExpr) root cur loc = filterOrExprLocated orExpr root cur loc-qSelectorLocated WildcardSelector _ cur loc = case cur of- (JSON.Object obj) -> V.fromList $ zip (locsWithKeys obj) (KM.elems obj)- (JSON.Array arr) -> V.zip (V.fromList (locsWithIdxs arr)) arr- _ -> V.empty- where- locsWithKeys obj = map (\x -> loc ++ "['" ++ K.toString x ++ "']") (KM.keys obj)- locsWithIdxs arr = map (\x -> loc ++ "[" ++ show x ++ "]") [0..(V.length arr)]---sliceArray :: (Maybe Int, Maybe Int, Int) -> Vector Value -> Vector Value-sliceArray (start,end,step) vec =- case compare step 0 of- GT -> getSliceForward (maybe 0 normalize start) (maybe len normalize end) step vec- LT -> getSliceReverse (maybe (len-1) normalize start) (maybe (-1) normalize end) step vec- EQ -> V.empty- where- -- TODO: Looks kinda ugly, make it pretty <3- len = V.length vec- normalize i = if i >= 0 then i else len + i-- getSliceForward st en stp arr = loop lower V.empty- where- (lower,upper) = (min (max st 0) len, min (max en 0) len)-- loop i acc =- if i < upper- then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)- else- acc-- getSliceReverse st en stp arr = loop upper V.empty- where- (lower,upper) = (min (max en (-1)) (len-1), min (max st (-1)) (len-1))-- loop i acc =- if lower < i- then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)- else- acc---sliceArrayLocated :: (Maybe Int, Maybe Int, Int) -> Vector (String,Value) -> Vector (String,Value)-sliceArrayLocated (start,end,step) vec =- case compare step 0 of- GT -> getSliceForward (maybe 0 normalize start) (maybe len normalize end) step vec- LT -> getSliceReverse (maybe (len-1) normalize start) (maybe (-1) normalize end) step vec- EQ -> V.empty- where- -- TODO: Looks kinda ugly, make it pretty <3- len = V.length vec- normalize i = if i >= 0 then i else len + i-- getSliceForward st en stp arr = loop lower V.empty- where- (lower,upper) = (min (max st 0) len, min (max en 0) len)-- loop i acc =- if i < upper- then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)- else- acc-- getSliceReverse st en stp arr = loop upper V.empty- where- (lower,upper) = (min (max en (-1)) (len-1), min (max st (-1)) (len-1))-- loop i acc =- if lower < i- then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)- else- acc--filterOrExpr :: LogicalOrExpr -> Value -> Value -> Vector Value-filterOrExpr expr root (JSON.Object obj) = V.filter (evaluateLogicalOrExpr expr root) (V.fromList $ KM.elems obj)-filterOrExpr expr root (JSON.Array arr) = V.filter (evaluateLogicalOrExpr expr root) arr-filterOrExpr _ _ _ = V.empty--filterOrExprLocated :: LogicalOrExpr -> Value -> Value -> String -> Vector (String,Value)-filterOrExprLocated expr root (JSON.Object obj) loc = V.filter (\(_,x) -> evaluateLogicalOrExpr expr root x) (V.fromList $ zip locsWithKeys (KM.elems obj))- where- locsWithKeys = map (\x -> loc ++ "['" ++ K.toString x ++ "']") (KM.keys obj)-filterOrExprLocated expr root (JSON.Array arr) loc = V.filter (\(_,x) -> evaluateLogicalOrExpr expr root x) (V.zip (V.fromList locsWithIdxs) arr)- where- locsWithIdxs = map (\x -> loc ++ "[" ++ show x ++ "]") [0..(V.length arr - 1)]-filterOrExprLocated _ _ _ _ = V.empty---evaluateLogicalOrExpr :: LogicalOrExpr -> Value -> Value -> Bool-evaluateLogicalOrExpr (LogicalOr exprs) root cur = any (\x -> evaluateLogicalAndExpr x root cur) exprs---evaluateLogicalAndExpr :: LogicalAndExpr -> Value -> Value -> Bool-evaluateLogicalAndExpr (LogicalAnd exprs) root cur = all (\x -> evaluateBasicExpr x root cur) exprs---evaluateBasicExpr :: BasicExpr -> Value -> Value -> Bool-evaluateBasicExpr (Paren expr) root cur = evaluateLogicalOrExpr expr root cur-evaluateBasicExpr (NotParen expr) root cur = not $ evaluateLogicalOrExpr expr root cur-evaluateBasicExpr (Test expr) root cur = evaluateTestExpr expr root cur-evaluateBasicExpr (NotTest expr) root cur = not $ evaluateTestExpr expr root cur-evaluateBasicExpr (Comparison expr) root cur = evaluateCompExpr expr root cur---evaluateTestExpr :: TestExpr -> Value -> Value -> Bool-evaluateTestExpr expr root cur = not $ null $ qQuery expr root cur---evaluateCompExpr :: ComparisonExpr -> Value -> Value -> Bool-evaluateCompExpr (Comp leftC op rightC) root cur = compareVals op (getComparableVal leftC root cur) (getComparableVal rightC root cur)---compareVals :: ComparisonOp -> Maybe Value -> Maybe Value -> Bool-compareVals Less (Just (JSON.String s1)) (Just (JSON.String s2)) = s1 < s2-compareVals Less (Just (JSON.Number n1)) (Just (JSON.Number n2)) = n1 < n2-compareVals Less _ _ = False--compareVals LessOrEqual o1 o2 = compareVals Less o1 o2 || compareVals Equal o1 o2-compareVals Greater o1 o2 = compareVals Less o2 o1-compareVals GreaterOrEqual o1 o2 = compareVals Less o2 o1 || compareVals Equal o1 o2-compareVals Equal o1 o2 = o1 == o2-compareVals NotEqual o1 o2 = o1 /= o2---getComparableVal :: Comparable -> Value -> Value -> Maybe Value-getComparableVal (CompLitNum num) _ _ = Just $ JSON.Number num-getComparableVal (CompLitString txt) _ _ = Just $ JSON.String txt-getComparableVal (CompLitBool bool) _ _ = Just $ JSON.Bool bool-getComparableVal CompLitNull _ _ = Just JSON.Null-getComparableVal (CompSQ SingularQuery{..}) root cur = case singularQueryType of- RootSQ -> traverseSingularQSegs (Just root) singularQuerySegments- CurrentSQ -> traverseSingularQSegs (Just cur) singularQuerySegments---traverseSingularQSegs :: Maybe Value -> [SingularQuerySegment] -> Maybe Value-traverseSingularQSegs = foldl lookupSingleQSeg----- TODO: There is a bug here, not existing shouldn't give null--- See: https://www.rfc-editor.org/rfc/rfc9535#name-examples-6-lookupSingleQSeg :: Maybe Value -> SingularQuerySegment -> Maybe Value-lookupSingleQSeg (Just (JSON.Object obj)) (NameSQSeg txt) = KM.lookup (K.fromText txt) obj-lookupSingleQSeg (Just (JSON.Array arr)) (IndexSQSeg idx) = (V.!?) arr idx-lookupSingleQSeg _ _ = Nothing+import Data.Aeson.JSONPath.Query.Query
+ src/Data/Aeson/JSONPath/Query/Filter.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE RecordWildCards #-}+module Data.Aeson.JSONPath.Query.Filter+ ( filterOrExpr+ , filterOrExprLocated )+ where++import Data.Aeson (Value)+import Data.Vector (Vector)++import qualified Data.Aeson as JSON+import qualified Data.Aeson.KeyMap as KM+import qualified Data.Aeson.Key as K+import qualified Data.Vector as V++import Data.Aeson.JSONPath.Types++import Prelude++filterOrExpr :: LogicalOrExpr Query -> QueryState -> Vector Value+filterOrExpr expr qS@QueryState{ curVal=(JSON.Object obj) } = V.filter (\cur -> evaluateLogicalOrExpr expr qS{ curVal=cur}) (V.fromList $ KM.elems obj)+filterOrExpr expr qS@QueryState{ curVal=(JSON.Array arr) } = V.filter (\cur -> evaluateLogicalOrExpr expr qS{ curVal=cur }) arr+filterOrExpr _ _ = V.empty++filterOrExprLocated :: LogicalOrExpr Query -> QueryState -> String -> Vector (String,Value)+filterOrExprLocated expr qS@QueryState{ curVal=(JSON.Object obj) } loc = V.filter (\(_,x) -> evaluateLogicalOrExpr expr qS{ curVal=x}) (V.fromList $ zip locsWithKeys (KM.elems obj))+ where+ locsWithKeys = map (\x -> loc ++ "['" ++ K.toString x ++ "']") (KM.keys obj)+filterOrExprLocated expr qS@QueryState{ curVal=(JSON.Array arr) } loc = V.filter (\(_,x) -> evaluateLogicalOrExpr expr qS{ curVal=x}) (V.zip (V.fromList locsWithIdxs) arr)+ where+ locsWithIdxs = map (\x -> loc ++ "[" ++ show x ++ "]") [0..(V.length arr - 1)]+filterOrExprLocated _ _ _ = V.empty+++evaluateLogicalOrExpr :: LogicalOrExpr Query -> QueryState -> Bool+evaluateLogicalOrExpr (LogicalOr exprs) qS = any (`evaluateLogicalAndExpr` qS) exprs+++evaluateLogicalAndExpr :: LogicalAndExpr Query -> QueryState -> Bool+evaluateLogicalAndExpr (LogicalAnd exprs) qS = all (`evaluateBasicExpr` qS) exprs+++evaluateBasicExpr :: BasicExpr Query -> QueryState -> Bool+evaluateBasicExpr (Paren expr) qS = evaluateLogicalOrExpr expr qS+evaluateBasicExpr (NotParen expr) qS = not $ evaluateLogicalOrExpr expr qS+evaluateBasicExpr (Test expr) qS = evaluateTestExpr expr qS+evaluateBasicExpr (NotTest expr) qS = not $ evaluateTestExpr expr qS+evaluateBasicExpr (Comparison expr) qS = evaluateCompExpr expr qS+++evaluateTestExpr :: TestExpr Query -> QueryState -> Bool+evaluateTestExpr (FilterQuery expr) qS@QueryState{..} = not $ null $ executeQuery expr qS+++evaluateCompExpr :: ComparisonExpr -> QueryState -> Bool+evaluateCompExpr (Comp leftC op rightC) qS = compareVals op (getComparableVal leftC qS) (getComparableVal rightC qS)+++compareVals :: ComparisonOp -> Maybe Value -> Maybe Value -> Bool+compareVals Less (Just (JSON.String s1)) (Just (JSON.String s2)) = s1 < s2+compareVals Less (Just (JSON.Number n1)) (Just (JSON.Number n2)) = n1 < n2+compareVals Less _ _ = False++compareVals LessOrEqual o1 o2 = compareVals Less o1 o2 || compareVals Equal o1 o2+compareVals Greater o1 o2 = compareVals Less o2 o1+compareVals GreaterOrEqual o1 o2 = compareVals Less o2 o1 || compareVals Equal o1 o2+compareVals Equal o1 o2 = o1 == o2+compareVals NotEqual o1 o2 = o1 /= o2+++getComparableVal :: Comparable -> QueryState -> Maybe Value+getComparableVal (CompLit lit) _ = + case lit of+ LitString txt -> Just $ JSON.String txt+ LitNum num -> Just $ JSON.Number num+ LitBool bool -> Just $ JSON.Bool bool+ LitNull -> Just JSON.Null++getComparableVal (CompSQ SingularQuery{..}) QueryState{..} = case singularQueryType of+ RootSQ -> traverseSingularQSegs (Just rootVal) singularQuerySegments+ CurrentSQ -> traverseSingularQSegs (Just curVal) singularQuerySegments+++traverseSingularQSegs :: Maybe Value -> [SingularQuerySegment] -> Maybe Value+traverseSingularQSegs = foldl lookupSingleQSeg+++lookupSingleQSeg :: Maybe Value -> SingularQuerySegment -> Maybe Value+lookupSingleQSeg (Just (JSON.Object obj)) (NameSQSeg txt) = KM.lookup (K.fromText txt) obj+lookupSingleQSeg (Just (JSON.Array arr)) (IndexSQSeg idx) = (V.!?) arr idx+lookupSingleQSeg _ _ = Nothing
+ src/Data/Aeson/JSONPath/Query/Query.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE RecordWildCards #-}+module Data.Aeson.JSONPath.Query.Query+ ( qQuery+ , qQueryLocated+ )+ where++import Control.Monad (join)+import Data.Aeson (Value)+import Data.Vector (Vector)++import qualified Data.Vector as V++import Data.Aeson.JSONPath.Types+import Data.Aeson.JSONPath.Query.Segment++import Prelude++-- | Runs the JSONPath Query+qQuery :: Query -> QueryState -> Vector Value+qQuery Query{..} qS@QueryState{..} = case queryType of+ Root -> foldl applySegment (V.singleton rootVal) querySegments+ Current -> foldl applySegment (V.singleton curVal) querySegments+ where+ applySegment :: Vector Value -> QuerySegment Query -> Vector Value+ applySegment vec seg = join $ V.map (\x -> qQuerySegment seg qS{ curVal = x }) vec++-- | Runs the JSONPath Query also returning node locations+qQueryLocated :: Query -> QueryState -> String -> Vector (String,Value)+qQueryLocated Query{..} qS@QueryState{..} loc = case queryType of+ Root -> foldl applySegment (V.singleton (loc,rootVal)) querySegments+ Current -> foldl applySegment (V.singleton (loc,curVal)) querySegments+ where+ applySegment :: Vector (String,Value) -> QuerySegment Query -> Vector (String,Value)+ applySegment vec seg = join $ V.map (\(location,cur) -> qQuerySegmentLocated seg qS{ curVal = cur } location) vec
+ src/Data/Aeson/JSONPath/Query/Segment.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE RecordWildCards #-}+module Data.Aeson.JSONPath.Query.Segment+ ( qQuerySegment+ , qQuerySegmentLocated+ )+ where++import Control.Monad (join)+import Data.Aeson (Value)+import Data.Vector (Vector)++import qualified Data.Aeson as JSON+import qualified Data.Aeson.KeyMap as KM+import qualified Data.Aeson.Key as K+import qualified Data.Vector as V++import Data.Aeson.JSONPath.Types+import Data.Aeson.JSONPath.Query.Selector++import Prelude++qQuerySegment :: QuerySegment Query -> QueryState -> Vector Value+qQuerySegment QuerySegment{..} qS@QueryState{..} = case segmentType of+ Child -> joinAfterMap $ V.singleton curVal+ Descendant -> joinAfterMap $ allElemsRecursive curVal+ where+ joinAfterMap vec = join $ V.map (\cur -> qSegment segment qS{ curVal = cur }) vec++qQuerySegmentLocated :: QuerySegment Query -> QueryState-> String -> Vector (String, Value)+qQuerySegmentLocated QuerySegment{..} qS@QueryState{..} loc = case segmentType of+ Child -> joinAfterMap $ V.singleton (loc,curVal)+ Descendant -> joinAfterMap $ allElemsRecursiveLocated (loc,curVal)+ where+ joinAfterMap vec = join $ V.map (\(location,cur) -> qSegmentLocated segment qS{ curVal = cur } location) vec++qSegment :: Segment Query -> QueryState -> Vector Value+qSegment (Bracketed sels) qS = V.concat $ map (`qSelector` qS) sels+qSegment (Dotted key) qS = qSelector (Name key) qS+qSegment WildcardSegment qS = qSelector WildcardSelector qS++qSegmentLocated :: Segment Query -> QueryState -> String -> Vector (String,Value)+qSegmentLocated (Bracketed sels) qS loc = V.concat $ map (\sel -> qSelectorLocated sel qS loc) sels+qSegmentLocated (Dotted key) qS loc = qSelectorLocated (Name key) qS loc+qSegmentLocated WildcardSegment qS loc = qSelectorLocated WildcardSelector qS loc++-- TODO: Looks kinda ugly, make it pretty <3+allElemsRecursive :: Value -> Vector Value+allElemsRecursive o@(JSON.Object obj) = V.concat [+ V.singleton o,+ V.concat $ map allElemsRecursive (KM.elems obj)+ ]+allElemsRecursive a@(JSON.Array arr) = V.concat [+ V.singleton a,+ V.concat $ map allElemsRecursive (V.toList arr)+ ]+allElemsRecursive _ = V.empty++-- TODO: Looks kinda ugly, make it pretty <3+allElemsRecursiveLocated :: (String,Value) -> Vector (String,Value)+allElemsRecursiveLocated (loc, o@(JSON.Object obj)) = V.concat [+ V.singleton (loc,o),+ V.concat $ zipWith (curry allElemsRecursiveLocated) keys (KM.elems obj)+ ]+ where+ keys = map (toPathKey loc) $ KM.keys obj+allElemsRecursiveLocated (loc, a@(JSON.Array arr)) = V.concat [+ V.singleton (loc,a),+ V.concat $ zipWith (curry allElemsRecursiveLocated) indices (V.toList arr)+ ]+ where+ indices = map (toPathIdx loc) [0..V.length arr - 1]+allElemsRecursiveLocated _ = V.empty++toPathKey :: String -> KM.Key -> String+toPathKey loc key = loc ++ "['" ++ escapeEscapees (K.toString key) ++ "']"+ where+ escapeEscapees :: String -> String+ escapeEscapees [] = []+ escapeEscapees (x:xs) = checkChar x ++ escapeEscapees xs+ where+ -- TODO: Do we need to escape unicode chars?+ checkChar '\\' = ['\\', '\\']+ checkChar '\'' = ['\\', '\'']+ checkChar '\b' = ['\\', 'b']+ checkChar '\r' = ['\\', 'r']+ checkChar '\t' = ['\\', 't']+ checkChar '\f' = ['\\', 'f']+ checkChar '\n' = ['\\', 'n']+ checkChar c = [c]++toPathIdx :: String -> Int -> String+toPathIdx loc idx = loc ++ "[" ++ show idx ++ "]"
+ src/Data/Aeson/JSONPath/Query/Selector.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE RecordWildCards #-}+module Data.Aeson.JSONPath.Query.Selector+ ( qSelector+ , qSelectorLocated+ )+ where++import Data.Aeson (Value)+import Data.Vector (Vector)+import Data.Text (Text)++import qualified Data.Aeson as JSON+import qualified Data.Aeson.KeyMap as KM+import qualified Data.Aeson.Key as K+import qualified Data.Text as T+import qualified Data.Vector as V++import Data.Aeson.JSONPath.Types+import Data.Aeson.JSONPath.Query.Filter++import Prelude++qSelector :: Selector Query -> QueryState -> Vector Value+qSelector (Name key) QueryState{curVal=(JSON.Object obj)} = maybe V.empty V.singleton $ KM.lookup (K.fromText key) obj+qSelector (Name _) _ = V.empty+qSelector (Index idx) QueryState{curVal=(JSON.Array arr)} = maybe V.empty V.singleton $ if idx >= 0 then (V.!?) arr idx else (V.!?) arr (idx + V.length arr)+qSelector (Index _) _ = V.empty+qSelector (ArraySlice startEndStep) QueryState{curVal=(JSON.Array arr) } = sliceArray startEndStep arr+qSelector (ArraySlice _) _ = V.empty+qSelector (Filter orExpr) qS = filterOrExpr orExpr qS+qSelector WildcardSelector QueryState{..} = case curVal of+ (JSON.Object obj) -> V.fromList $ KM.elems obj+ (JSON.Array arr) -> arr+ _ -> V.empty+++qSelectorLocated :: Selector Query -> QueryState -> String -> Vector (String,Value)+qSelectorLocated (Name key) QueryState{curVal=(JSON.Object obj)} loc = maybe V.empty (\x-> V.singleton (toPathKey loc key, x)) $ KM.lookup (K.fromText key) obj+qSelectorLocated (Name _) _ _ = V.empty+qSelectorLocated (Index idx) QueryState{curVal=(JSON.Array arr)} loc = maybe V.empty (\x-> V.singleton (newLocation, x)) $ (V.!?) arr (getIndex idx)+ where+ newLocation = loc ++ "[" ++ show (getIndex idx) ++ "]"+ getIndex i = if i >= 0 then i else i + V.length arr+qSelectorLocated (Index _) _ _ = V.empty+qSelectorLocated (ArraySlice (start,end,step)) QueryState{curVal=(JSON.Array arr)} loc = sliceArrayLocated (start,end,step) $ V.zip (V.fromList locs) arr+ where+ locs = [ loc ++ "[" ++ show i ++ "]" | i <- indices ]+ indices = [0..(V.length arr - 1)]+qSelectorLocated (ArraySlice _) _ _ = V.empty+qSelectorLocated (Filter orExpr) qS loc = filterOrExprLocated orExpr qS loc+qSelectorLocated WildcardSelector QueryState{..} loc = case curVal of+ (JSON.Object obj) -> V.fromList $ zip (locsWithKeys obj) (KM.elems obj)+ (JSON.Array arr) -> V.zip (V.fromList (locsWithIdxs arr)) arr+ _ -> V.empty+ where+ locsWithKeys obj = map (toPathKey loc . K.toText) (KM.keys obj)+ locsWithIdxs arr = map (\x -> loc ++ "[" ++ show x ++ "]") [0..(V.length arr)]+++sliceArray :: (Maybe Int, Maybe Int, Int) -> Vector Value -> Vector Value+sliceArray (start,end,step) vec =+ case compare step 0 of+ GT -> getSliceForward (maybe 0 normalize start) (maybe len normalize end) step vec+ LT -> getSliceReverse (maybe (len-1) normalize start) (maybe (-1) normalize end) step vec+ EQ -> V.empty+ where+ -- TODO: Looks kinda ugly, make it pretty <3+ len = V.length vec+ normalize i = if i >= 0 then i else len + i++ getSliceForward st en stp arr = loop lower V.empty+ where+ (lower,upper) = (min (max st 0) len, min (max en 0) len)++ loop i acc =+ if i < upper+ then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)+ else+ acc++ getSliceReverse st en stp arr = loop upper V.empty+ where+ (lower,upper) = (min (max en (-1)) (len-1), min (max st (-1)) (len-1))++ loop i acc =+ if lower < i+ then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)+ else+ acc+++sliceArrayLocated :: (Maybe Int, Maybe Int, Int) -> Vector (String,Value) -> Vector (String,Value)+sliceArrayLocated (start,end,step) vec =+ case compare step 0 of+ GT -> getSliceForward (maybe 0 normalize start) (maybe len normalize end) step vec+ LT -> getSliceReverse (maybe (len-1) normalize start) (maybe (-1) normalize end) step vec+ EQ -> V.empty+ where+ -- TODO: Looks kinda ugly, make it pretty <3+ len = V.length vec+ normalize i = if i >= 0 then i else len + i++ getSliceForward st en stp arr = loop lower V.empty+ where+ (lower,upper) = (min (max st 0) len, min (max en 0) len)++ loop i acc =+ if i < upper+ then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)+ else+ acc++ getSliceReverse st en stp arr = loop upper V.empty+ where+ (lower,upper) = (min (max en (-1)) (len-1), min (max st (-1)) (len-1))++ loop i acc =+ if lower < i+ then loop (i+stp) $ V.snoc acc $ (V.!) arr (normalize i)+ else+ acc+++toPathKey :: String -> Text -> String+toPathKey loc key = loc ++ "['" ++ escapeEscapees (T.unpack key) ++ "']"+ where+ escapeEscapees :: String -> String+ escapeEscapees [] = []+ escapeEscapees (x:xs) = checkChar x ++ escapeEscapees xs+ where+ -- TODO: Do we need to escape unicode chars?+ checkChar '\\' = ['\\', '\\']+ checkChar '\'' = ['\\', '\'']+ checkChar '\b' = ['\\', 'b']+ checkChar '\r' = ['\\', 'r']+ checkChar '\t' = ['\\', 't']+ checkChar '\f' = ['\\', 'f']+ checkChar '\n' = ['\\', 'n']+ checkChar c = [c]
− src/Data/Aeson/JSONPath/Query/Types.hs
@@ -1,139 +0,0 @@-{-# LANGUAGE DeriveLift #-}-{- |-Module : Data.Aeson.JSONPath.Query.Types-Description : ADTs used internally-Copyright : (c) 2024-2025 Taimoor Zaeem-License : MIT-Maintainer : Taimoor Zaeem <mtaimoorzaeem@gmail.com>-Stability : Experimental-Portability : Portable--This module contains the data structures.--}-module Data.Aeson.JSONPath.Query.Types- (Query (..)- , QueryType (..)- , Segment (..)- , QuerySegment (..)- , SegmentType (..)- , Selector (..)- , LogicalOrExpr (..)- , LogicalAndExpr (..)- , BasicExpr (..)- , TestExpr- , ComparisonExpr (..)- , ComparisonOp (..)- , Comparable(..)- , SingularQuery (..)- , SingularQueryType (..)- , SingularQuerySegment (..)- )- where--import Data.Text (Text)-import Data.Scientific (Scientific)-import Language.Haskell.TH.Syntax (Lift)--import Prelude---- |-data QueryType - = Root - | Current- deriving (Eq, Show, Lift)---- |-data Query = Query- { queryType :: QueryType- , querySegments :: [QuerySegment]- } deriving (Eq, Show, Lift)---- |-data SegmentType- = Child- | Descendant- deriving (Eq, Show, Lift)---- |-data QuerySegment = QuerySegment- { segmentType :: SegmentType- , segment :: Segment- } deriving (Eq, Show, Lift)---- |-data Segment- = Bracketed [Selector]- | Dotted Text- | WildcardSegment- deriving (Eq, Show, Lift)---- |-data Selector- = Name Text- | Index Int- | ArraySlice (Maybe Int, Maybe Int, Int)- | Filter LogicalOrExpr- | WildcardSelector- deriving (Eq, Show, Lift)---- |-newtype LogicalOrExpr- = LogicalOr [LogicalAndExpr]- deriving (Eq, Show, Lift)---- |-newtype LogicalAndExpr- = LogicalAnd [BasicExpr]- deriving (Eq, Show, Lift)---- |-data BasicExpr- = Paren LogicalOrExpr -- ( expr )- | NotParen LogicalOrExpr -- not (expr)- | Test TestExpr -- expr- | NotTest TestExpr -- not expr- | Comparison ComparisonExpr- deriving (Eq, Show, Lift)---- |-type TestExpr = Query---- |-data ComparisonExpr- = Comp Comparable ComparisonOp Comparable- deriving (Eq, Show, Lift)---- |-data ComparisonOp- = Less- | LessOrEqual- | Greater- | GreaterOrEqual- | Equal- | NotEqual- deriving (Eq, Show, Lift)---- |-data Comparable- = CompLitString Text- | CompLitNum Scientific- | CompLitBool Bool- | CompLitNull- | CompSQ SingularQuery- deriving (Eq, Show, Lift)---- |-data SingularQueryType = RootSQ | CurrentSQ- deriving (Eq, Show, Lift)---- |-data SingularQuery = SingularQuery- { singularQueryType :: SingularQueryType- , singularQuerySegments :: [SingularQuerySegment]- } deriving (Eq, Show, Lift)---- |-data SingularQuerySegment- = NameSQSeg Text- | IndexSQSeg Int- deriving (Eq, Show, Lift)
+ src/Data/Aeson/JSONPath/Types.hs view
@@ -0,0 +1,30 @@+{- |+Module : Data.Aeson.JSONPath.Types+Description : Types related to JSONPath elements+Copyright : (c) 2024-2025 Taimoor Zaeem+License : MIT+Maintainer : Taimoor Zaeem <mtaimoorzaeem@gmail.com>+Stability : Experimental+Portability : Portable++This module contains all the data structures related to JSONPath+-}+module Data.Aeson.JSONPath.Types+ ( + module Data.Aeson.JSONPath.Types.Query++ , module Data.Aeson.JSONPath.Types.Segment++ , module Data.Aeson.JSONPath.Types.Selector++ , module Data.Aeson.JSONPath.Types.Filter+ )+ where++import Data.Aeson.JSONPath.Types.Query++import Data.Aeson.JSONPath.Types.Segment++import Data.Aeson.JSONPath.Types.Selector++import Data.Aeson.JSONPath.Types.Filter
+ src/Data/Aeson/JSONPath/Types/Filter.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE DeriveLift #-}+module Data.Aeson.JSONPath.Types.Filter+ (LogicalOrExpr (..)+ , LogicalAndExpr (..)+ , BasicExpr (..)+ , TestExpr (..)+ , ComparisonExpr (..)+ , ComparisonOp (..)+ , Comparable (..)+ , Literal (..)+ , SingularQueryType (..)+ , SingularQuery (..)+ , SingularQuerySegment (..)+ )+ where++import Data.Text (Text)+import Data.Scientific (Scientific)++import Language.Haskell.TH.Syntax (Lift)++import Prelude++-- |+newtype LogicalOrExpr a+ = LogicalOr [LogicalAndExpr a]+ deriving (Eq, Show, Lift)++-- |+newtype LogicalAndExpr a+ = LogicalAnd [BasicExpr a]+ deriving (Eq, Show, Lift)++-- |+data BasicExpr a+ = Paren (LogicalOrExpr a) -- ( expr )+ | NotParen (LogicalOrExpr a) -- not (expr)+ | Test (TestExpr a) -- query+ | NotTest (TestExpr a) -- not query+ | Comparison ComparisonExpr+ deriving (Eq, Show, Lift)++-- |+newtype TestExpr a+ = FilterQuery a+ deriving (Eq, Show, Lift)++-- |+data ComparisonExpr+ = Comp Comparable ComparisonOp Comparable+ deriving (Eq, Show, Lift)++-- |+data ComparisonOp+ = Less+ | LessOrEqual+ | Greater+ | GreaterOrEqual+ | Equal+ | NotEqual+ deriving (Eq, Show, Lift)++-- |+data Comparable+ = CompLit Literal+ | CompSQ SingularQuery+ deriving (Eq, Show, Lift)++-- |+data Literal+ = LitString Text+ | LitNum Scientific+ | LitBool Bool+ | LitNull+ deriving (Eq, Show, Lift)++-- |+data SingularQueryType = RootSQ | CurrentSQ+ deriving (Eq, Show, Lift)++-- |+data SingularQuery = SingularQuery+ { singularQueryType :: SingularQueryType+ , singularQuerySegments :: [SingularQuerySegment]+ } deriving (Eq, Show, Lift)++-- |+data SingularQuerySegment+ = NameSQSeg Text+ | IndexSQSeg Int+ deriving (Eq, Show, Lift)
+ src/Data/Aeson/JSONPath/Types/Query.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE DeriveLift #-}+module Data.Aeson.JSONPath.Types.Query+ ( Query (..)+ , QueryType (..)+ , QueryState (..)+ )+ where++import Data.Aeson (Value)+import Data.Vector (Vector)++import Data.Aeson.JSONPath.Types.Segment (QuerySegment (..))+import Language.Haskell.TH.Syntax (Lift)++import Prelude++-- |+data QueryState = QueryState+ { rootVal :: Value+ , curVal :: Value+ , executeQuery :: Query -> QueryState -> Vector Value+ }++-- |+data QueryType + = Root + | Current+ deriving (Eq, Show, Lift)++-- |+data Query = Query+ { queryType :: QueryType+ , querySegments :: [QuerySegment Query]+ } deriving (Eq, Show, Lift)
+ src/Data/Aeson/JSONPath/Types/Segment.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE DeriveLift #-}+module Data.Aeson.JSONPath.Types.Segment+ (Segment (..)+ , QuerySegment (..)+ , SegmentType (..)+ )+ where++import Data.Aeson.JSONPath.Types.Selector (Selector (..))+import Data.Text (Text)+import Language.Haskell.TH.Syntax (Lift)++import Prelude++-- |+data SegmentType+ = Child+ | Descendant+ deriving (Eq, Show, Lift)++-- |+data QuerySegment a = QuerySegment+ { segmentType :: SegmentType+ , segment :: Segment a+ } deriving (Eq, Show, Lift)++-- |+data Segment a+ = Bracketed [Selector a]+ | Dotted Text+ | WildcardSegment+ deriving (Eq, Show, Lift)
+ src/Data/Aeson/JSONPath/Types/Selector.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE DeriveLift #-}+module Data.Aeson.JSONPath.Types.Selector+ (Selector (..))+ where++import Data.Aeson.JSONPath.Types.Filter (LogicalOrExpr (..))+import Data.Text (Text)+import Language.Haskell.TH.Syntax (Lift)++import Prelude++-- |+data Selector a+ = Name Text+ | Index Int+ | ArraySlice (Maybe Int, Maybe Int, Int)+ | Filter (LogicalOrExpr a)+ | WildcardSelector+ deriving (Eq, Show, Lift)
− test/ComplianceSpec.hs
@@ -1,85 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE NamedFieldPuns #-}-module ComplianceSpec- ( spec- , TestSuite (..))- where--import qualified Data.Aeson as JSON-import qualified Data.Vector as V-import qualified Text.ParserCombinators.Parsec as P--import Control.Monad (mzero)-import Data.Aeson ((.:),(.:?),Value)-import Data.Aeson.JSONPath (query)-import Data.Aeson.JSONPath.Parser (pQuery)-import Data.Either (isLeft, fromRight)-import Data.Vector (Vector)--import Test.Hspec-import Prelude--data TestSuite = TestSuite- { tests :: [TestCase]- } deriving (Show)--instance JSON.FromJSON TestSuite where- parseJSON (JSON.Object o) =- TestSuite- <$> o .: "tests"-- parseJSON _ = mzero--data TestCase = TestCase- { name :: String- , selector :: String- , document :: Maybe Value- , result :: Maybe (Vector Value)- , results :: Maybe [Vector Value]- , invalidSel :: Maybe Bool- , tags :: Maybe [String]- } deriving (Show)--instance JSON.FromJSON TestCase where- parseJSON (JSON.Object o) =- TestCase- <$> o .: "name"- <*> o .: "selector"- <*> o .:? "document"- <*> o .:? "result"- <*> o .:? "results"- <*> o .:? "invalid_selector"- <*> o .:? "tags"-- parseJSON _ = mzero--spec :: TestSuite -> Spec-spec TestSuite{tests} = do- describe "compliance tests" $ do- mapM_ runTestCase tests---runTestCase :: TestCase -> SpecWith ()--- skip function extension tests-runTestCase tc@TestCase{tags=Just xs, ..} =- if (elem "function" xs)- then xit name pending- else- runTestCase tc{tags=Nothing}---- invalid selector should not parse correctly-runTestCase TestCase{invalidSel=(Just True), ..} =- it name $- P.parse pQuery "" selector `shouldSatisfy` isLeft---- if result is deterministic (one json)-runTestCase TestCase{result=(Just r), document=(Just doc), ..} =- it name $- query selector doc `shouldBe` Right r---- if result is non-deterministic (any json from the list of results)-runTestCase TestCase{results=(Just rs), document=(Just doc), ..} = do- it name $- query selector doc `shouldSatisfy` (\x -> elem (fromRight V.empty x) rs)--runTestCase _ = pure ()
− test/LocatedSpec.hs
@@ -1,143 +0,0 @@-module LocatedSpec- ( spec )- where--import qualified Data.Aeson as JSON-import qualified Data.Vector as V--import Data.Aeson.JSONPath (queryLocatedQQ, jsonPath)-import Data.Aeson.QQ.Simple (aesonQQ)-import Data.Vector (Vector)-import Test.Hspec--import Prelude--getVector :: JSON.Value -> Vector JSON.Value-getVector (JSON.Array arr) = arr-getVector _ = V.empty---- taken from https://serdejsonpath.live/-rootDoc :: JSON.Value-rootDoc = [aesonQQ|{- "store": {- "books": [- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]- }- }|]---storeDoc :: JSON.Value-storeDoc = [aesonQQ|- {- "books": [- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]- }|]--booksDoc :: JSON.Value-booksDoc = [aesonQQ| [- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]|]---books0Doc :: JSON.Value-books0Doc = [aesonQQ|[- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- }- ]|]---spec :: Spec-spec = do- describe "test queryLocated" $ do- it "returns root document when query is $" $- queryLocatedQQ [jsonPath|$|] rootDoc `shouldBe` V.singleton ("$",rootDoc)-- it "returns store object when queryQQ is $.store" $- queryLocatedQQ [jsonPath|$.store|] rootDoc `shouldBe` V.fromList [("$['store']",storeDoc)]-- it "returns store object when queryQQ is $['store']" $- queryLocatedQQ [jsonPath|$['store']|] rootDoc `shouldBe` V.fromList [("$['store']",storeDoc)]-- it "returns books array when queryQQ is $.store.books" $- queryLocatedQQ [jsonPath|$.store.books|] rootDoc `shouldBe` V.fromList [("$['store']['books']",booksDoc)]-- it "returns 0-index book item, $.store.books[0]" $- queryLocatedQQ [jsonPath|$.store.books[0]|] rootDoc `shouldBe` V.zip (V.singleton "$['store']['books'][0]") (getVector books0Doc)-- it "returns 0-index book item, $.store.books[-4]" $- queryLocatedQQ [jsonPath|$.store.books[-4]|] rootDoc `shouldBe` V.zip (V.singleton "$['store']['books'][0]") (getVector books0Doc)
− test/Main.hs
@@ -1,45 +0,0 @@-module Main- ( main )- where--import qualified Data.Aeson as JSON-import qualified Test.Hspec as HS-import qualified Data.Text.Encoding as T-import qualified Data.Text.IO as TIO--import Data.Either (fromRight)--import qualified ParserSpec-import qualified QuerySpec-import qualified ComplianceSpec-import qualified LocatedSpec-import qualified Paths_aeson_jsonpath as Paths--import ComplianceSpec (TestSuite (..))--import Test.Hspec.Runner-import Prelude--allSpecs :: Either String TestSuite -> Spec-allSpecs cts = do- HS.describe "Run all tests" $ do- ParserSpec.spec- QuerySpec.spec- ComplianceSpec.spec (fromRight TestSuite{tests=[]} cts)- LocatedSpec.spec--readCtsFile :: FilePath -> IO (Either String TestSuite)-readCtsFile filePath = do- contents <- TIO.readFile filePath- return $ JSON.eitherDecodeStrict' $ T.encodeUtf8 contents--main :: IO ()-main = do- file <- Paths.getDataFileName "test/cts.json"- cts <- readCtsFile file- summary <- hspecWithResult defaultConfig - { configColorMode = ColorAuto- } (allSpecs cts)- - putStrLn $ "Total tests: " ++ show (summaryExamples summary)- putStrLn $ "Failures: " ++ show (summaryFailures summary)
− test/ParserSpec.hs
@@ -1,442 +0,0 @@-module ParserSpec- ( spec )- where--import qualified Text.ParserCombinators.Parsec as P--import Data.Aeson.JSONPath.Parser (pQuery)-import Data.Either (isLeft)--import Data.Aeson.JSONPath.Query.Types-import Test.Hspec-import Prelude--spec :: Spec-spec = do- describe "Parse query string" $ do- it "parses query: $" $- P.parse pQuery "" "$"- `shouldBe`- Right (Query{queryType=Root,querySegments=[]})-- it "parses query: $.store" $- P.parse pQuery "" "$.store"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }]- }-- it "parses query: $['store']" $- P.parse pQuery "" "$['store']"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [Name "store"]- }]- }-- it "parses query: $.store.books" $- P.parse pQuery "" "$.store.books"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }]- }-- it "parses query: $.store.books[0]" $- P.parse pQuery "" "$.store.books[0]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Index 0]- }]- }-- it "parses query: $.store.books[0,2]" $- P.parse pQuery "" "$.store.books[0,2]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Index 0, Index 2]- }]- }-- it "parses query: $.store.books[1:3]" $- P.parse pQuery "" "$.store.books[1:3]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [ArraySlice (Just 1, Just 3, 1)]- }]- }-- it "parses query: $.store.books[1:4:2]" $- P.parse pQuery "" "$.store.books[1:4:2]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [ArraySlice (Just 1, Just 4, 2)]- }]- }-- it "parses query: $.store.books[-1:-4:-2]" $- P.parse pQuery "" "$.store.books[-1:-4:-2]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [ArraySlice (Just (-1), Just (-4), (-2))]- }]- }-- it "parses query: $.store.books[1:3, 0, 1]" $- P.parse pQuery "" "$.store.books[1:3, 0, 1]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [ArraySlice (Just 1, Just 3, 1), Index 0, Index 1]- }]- }-- it "parses query: $.*" $- P.parse pQuery "" "$.*" - `shouldBe` - Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = WildcardSegment- }]- }-- it "parses query: $[*]" $- P.parse pQuery "" "$[*]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [WildcardSelector]- }]- }-- it "parses query: $..*" $- P.parse pQuery "" "$..*"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Descendant,- segment = WildcardSegment- }]- }-- it "parses query: $..[*]" $- P.parse pQuery "" "$..[*]"- `shouldBe` - Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Descendant,- segment = Bracketed [WildcardSelector]- }]- }-- it "fails with $.1startsWithNum" $- P.parse pQuery "" "$.1startsWithNum"- `shouldSatisfy` isLeft-- it "parses query $.©®±×÷Ωπ•€→∀∃∈≠≤≥✓λ" $- P.parse pQuery "" "$.©®±×÷Ωπ•€→∀∃∈≠≤≥✓λ"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "©®±×÷Ωπ•€→∀∃∈≠≤≥✓λ"- }]- }-- it "parses query: $._" $- P.parse pQuery "" "$._"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "_"- }]- }-- it "parses query: $.underscore_key" $- P.parse pQuery "" "$.underscore_key"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "underscore_key"- }]- }-- it "parses query: $[0,TAB/LINEFEED/RETURN/SPACE1]" $- P.parse pQuery "" "$[0,\n\t\r 1]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [Index 0, Index 1]- }]- }-- describe "parses JSPFilter Query" $ do- it "$[?@.category == 'reference']" $- P.parse pQuery "" "$[?@.category == 'reference']"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "category"]- }) Equal (CompLitString "reference"))]])]- }]- }-- it "test expr: $..books[?@.price].title" $- P.parse pQuery "" "$..books[?@.price].title"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Descendant,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Test Query {- queryType = Current,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "price"- }]- }]])]- }, QuerySegment {- segmentType = Child,- segment = Dotted "title"- }]- }-- it "and expr: $[?@.price < 20 && @.price > 10]" $- P.parse pQuery "" "$[?@.price < 20 && @.price > 10]" - `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Less (CompLitNum 20.0)), Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Greater (CompLitNum 10.0))]])]- }]- }-- it "or expr: $[?@.price < 20 || @.price > 10]" $- P.parse pQuery "" "$[?@.price < 20 || @.price > 10]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Less (CompLitNum 20.0))], LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Greater (CompLitNum 10.0))]])]- }]- }-- it "root filter: $..books[?$.price].title" $- P.parse pQuery "" "$..books[?$.price].title"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Descendant,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Test Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "price"- }]- }]])]- }, QuerySegment {- segmentType = Child,- segment = Dotted "title"- }]- }-- it "not expr: $[?!(@.price < 20 && @.price > 10)]" $- P.parse pQuery "" "$[?!(@.price < 20 && @.price > 10)]" - `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [NotParen (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Less (CompLitNum 20.0)), Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Greater (CompLitNum 10.0))]])]])]- }]- }-- it "scientific: $.store.books[?@.price < -1e20]" $- P.parse pQuery "" "$.store.books[?@['price'] < -1e20]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Less (CompLitNum (-1.0e20)))]])]- }]- }-- it "double: $.store.books[?@.price < 0.01]" $- P.parse pQuery "" "$.store.books[?@['price'] < 0.01]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "price"]- }) Less (CompLitNum (1.0e-2)))]])]- }]- }-- it "bool: $.store.books[?@.is_available == true]" $- P.parse pQuery "" "$.store.books[?@.is_available == true]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "is_available"]- }) Equal (CompLitBool True))]])]- }]- }-- it "null: $.store.books[?@.is_available == null]" $- P.parse pQuery "" "$.store.books[?@.is_available == null]"- `shouldBe`- Right Query {- queryType = Root,- querySegments = [QuerySegment {- segmentType = Child,- segment = Dotted "store"- }, QuerySegment {- segmentType = Child,- segment = Dotted "books"- }, QuerySegment {- segmentType = Child,- segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {- singularQueryType = CurrentSQ,- singularQuerySegments = [NameSQSeg "is_available"]- }) Equal CompLitNull)]])]- }]- }
− test/QuerySpec.hs
@@ -1,342 +0,0 @@-module QuerySpec- ( spec )- where--import qualified Data.Aeson as JSON-import qualified Data.Vector as V--import Data.Aeson.JSONPath (queryQQ, jsonPath)-import Data.Aeson.QQ.Simple (aesonQQ)-import Data.Vector (Vector)-import Test.Hspec--import Prelude--getVector :: JSON.Value -> Vector JSON.Value-getVector (JSON.Array arr) = arr-getVector _ = V.empty---- taken from https://serdejsonpath.live/-rootDoc :: JSON.Value-rootDoc = [aesonQQ|{- "store": {- "books": [- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]- }- }|]---storeDoc :: JSON.Value-storeDoc = [aesonQQ|- {- "books": [- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]- }|]--booksDoc :: JSON.Value-booksDoc = [aesonQQ| [- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]|]---books0Doc :: JSON.Value-books0Doc = [aesonQQ|[- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- }- ]|]--books0And2Doc :: JSON.Value-books0And2Doc = [aesonQQ|[- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- }- ]|]--books1To3Doc :: JSON.Value-books1To3Doc = [aesonQQ|[- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- }- ]|]--books1To3And0And1Doc :: JSON.Value-books1To3And0And1Doc = [aesonQQ|[- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Guns, Germs, and Steel",- "author": "Jared Diamond",- "category": "reference",- "price": 24.99- },- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- }- ]|]--lessThanPrice20Books :: JSON.Value-lessThanPrice20Books = [aesonQQ| [- {- "title": "David Copperfield",- "author": "Charles Dickens",- "category": "fiction",- "price": 12.99- },- {- "title": "Moby Dick",- "author": "Herman Melville",- "category": "fiction",- "price": 8.99- },- {- "title": "Crime and Punishment",- "author": "Fyodor Dostoevsky",- "category": "fiction",- "price": 19.99- }- ]|]--alphaArr :: JSON.Value-alphaArr = [aesonQQ| ["a","b","c","d","e","f","g"] |]--fgArr :: JSON.Value-fgArr = [aesonQQ| ["f","g"] |]--bdArr :: JSON.Value-bdArr = [aesonQQ| ["b","d"] |]--fdArr :: JSON.Value-fdArr = [aesonQQ| ["f","d"] |]--gfedcbaArr :: JSON.Value-gfedcbaArr = [aesonQQ| ["g","f","e","d","c","b","a"] |]--rfcExample1 :: JSON.Value-rfcExample1 = [aesonQQ| {- "o": {"j": 1, "k": 2},- "a": [5, 3, [{"j": 4}, {"k": 6}]]- } |]--rfcExample1Desc :: JSON.Value-rfcExample1Desc = [aesonQQ| [- [5, 3, [{"j": 4}, {"k": 6}]],- {"j": 1, "k": 2},- 5,- 3,- [{"j": 4}, {"k": 6}],- {"j": 4},- {"k": 6},- 4,- 6,- 1,- 2- ]|]--boolsAndNulls :: JSON.Value-boolsAndNulls = [aesonQQ| [- { "a": true },- { "a": false },- { "a": null }- ]|]---boolsAndNullsA :: JSON.Value-boolsAndNullsA = [aesonQQ| [{ "a": true }] |]--boolsAndNullsB :: JSON.Value-boolsAndNullsB = [aesonQQ| [{ "a": false }] |]--boolsAndNullsC :: JSON.Value-boolsAndNullsC = [aesonQQ| [{ "a": null }] |]--spec :: Spec-spec = do- describe "test query" $ do- it "returns root document when query is $" $- queryQQ [jsonPath|$|] rootDoc `shouldBe` V.singleton rootDoc-- it "returns store object when queryQQ is $.store" $- queryQQ [jsonPath|$.store|] rootDoc `shouldBe` V.singleton storeDoc-- it "returns store object when queryQQ is $['store']" $- queryQQ [jsonPath|$['store']|] rootDoc `shouldBe` V.singleton storeDoc-- it "returns books array when queryQQ is $.store.books" $- queryQQ [jsonPath|$.store.books|] rootDoc `shouldBe` V.singleton booksDoc-- it "returns 0-index book item when queryQQ is $.store.books[0]" $- queryQQ [jsonPath|$.store.books[0]|] rootDoc `shouldBe` getVector books0Doc-- it "returns 0-index book item when queryQQ is $.store.books[-4]" $- queryQQ [jsonPath|$.store.books[-4]|] rootDoc `shouldBe` getVector books0Doc-- it "returns 0,2-index item when queryQQ is $.store.books[0,2]" $- queryQQ [jsonPath|$.store.books[0,2]|] rootDoc `shouldBe` getVector books0And2Doc-- it "returns 1To3-index when queryQQ is $.store.books[1:3]" $- queryQQ [jsonPath|$.store.books[1:3]|] rootDoc `shouldBe` getVector books1To3Doc-- it "returns 1To3-index and 0,1-index when queryQQ is $.store.books[1:3,0,1]" $- queryQQ [jsonPath|$.store.books[1:3,0,1]|] rootDoc `shouldBe` getVector books1To3And0And1Doc-- it "returns slice with queryQQ $[5:]" $- queryQQ [jsonPath|$[5:]|] alphaArr `shouldBe` getVector fgArr-- it "returns slice with queryQQ $[1:5:2]" $- queryQQ [jsonPath|$[1:5:2]|] alphaArr `shouldBe` getVector bdArr-- it "returns slice with queryQQ $[5:1:-2]" $- queryQQ [jsonPath|$[5:1:-2]|] alphaArr `shouldBe` getVector fdArr-- it "returns slice with queryQQ $[::-1]" $- queryQQ [jsonPath|$[::-1]|] alphaArr `shouldBe` getVector gfedcbaArr-- it "returns root with queryQQ $.*" $- queryQQ [jsonPath|$.*|] rootDoc `shouldBe` V.singleton storeDoc-- it "returns root with queryQQ $[*]" $- queryQQ [jsonPath|$[*]|] rootDoc `shouldBe` V.singleton storeDoc-- it "returns descendants with queryQQ $..*" $- queryQQ [jsonPath|$..*|] rfcExample1 `shouldBe` getVector rfcExample1Desc-- it "returns descendants with queryQQ $..[*]" $- queryQQ [jsonPath|$..[*]|] rfcExample1 `shouldBe` getVector rfcExample1Desc-- it "returns with filtering: number comparison" $- queryQQ [jsonPath|$.store.books[?@.price < 20]|] rootDoc- `shouldBe` getVector lessThanPrice20Books-- it "returns with filtering: not operator" $- queryQQ [jsonPath|$.store.books[?!(@.price < 20)]|] rootDoc- `shouldBe` getVector books0Doc-- it "returns with filtering: true value" $- queryQQ [jsonPath|$[?@.a == true]|] boolsAndNulls- `shouldBe` getVector boolsAndNullsA-- it "returns with filtering: false value" $- queryQQ [jsonPath|$[?@.a == false]|] boolsAndNulls- `shouldBe` getVector boolsAndNullsB-- it "returns with filtering: null value" $- queryQQ [jsonPath|$[?@.a == null]|] boolsAndNulls- `shouldBe` getVector boolsAndNullsC-- it "returns with filtering: string comparison" $- queryQQ [jsonPath|$.store.books[?@.author == 'Jared Diamond']|] rootDoc- `shouldBe` getVector books0Doc-- it "returns with filtering: test expression" $- queryQQ [jsonPath|$.store.books[?@.author]|] rootDoc- `shouldBe` getVector booksDoc-- it "returns with filtering: test expr gives empty with non-existent key" $- queryQQ [jsonPath|$.store.books[?@.not_here]|] rootDoc- `shouldBe` V.empty
+ test/compliance/ComplianceSpec.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE NamedFieldPuns #-}+module ComplianceSpec+ ( spec+ , TestSuite (..))+ where++import qualified Data.Aeson as JSON+import qualified Data.Vector as V+import qualified Text.ParserCombinators.Parsec as P++import Control.Monad (mzero)+import Data.Aeson ((.:),(.:?),Value)+import Data.Aeson.JSONPath (query, queryLocated)+import Data.Aeson.JSONPath.Parser (pQuery)+import Data.Either (isLeft, fromRight)+import Data.Vector (Vector)++import Test.Hspec+import Prelude++newtype TestSuite = TestSuite+ { tests :: [TestCase]+ } deriving (Show)++instance JSON.FromJSON TestSuite where+ parseJSON (JSON.Object o) =+ TestSuite+ <$> o .: "tests"++ parseJSON _ = mzero++data TestCase = TestCase+ { name :: String+ , selector :: String+ , document :: Maybe Value+ , result :: Maybe (Vector Value)+ , results :: Maybe [Vector Value]+ , resultPaths :: Maybe (Vector String)+ , resultsPaths :: Maybe [Vector String]+ , invalidSel :: Maybe Bool+ , tags :: Maybe [String]+ } deriving (Show)++instance JSON.FromJSON TestCase where+ parseJSON (JSON.Object o) =+ TestCase+ <$> o .: "name"+ <*> o .: "selector"+ <*> o .:? "document"+ <*> o .:? "result"+ <*> o .:? "results"+ <*> o .:? "result_paths"+ <*> o .:? "results_paths"+ <*> o .:? "invalid_selector"+ <*> o .:? "tags"++ parseJSON _ = mzero++spec :: TestSuite -> Spec+spec TestSuite{tests} = do+ describe "compliance tests" $ do+ mapM_ runTestCase tests+++runTestCase :: TestCase -> SpecWith ()+-- skip function extension tests+runTestCase tc@TestCase{tags=Just xs, ..} =+ if "function" `elem` xs+ then xit name pending+ else+ runTestCase tc{tags=Nothing}++-- invalid selector should not parse correctly+runTestCase TestCase{invalidSel=(Just True), ..} =+ it name $+ P.parse pQuery "" selector `shouldSatisfy` isLeft++-- if result is deterministic (one json)+runTestCase TestCase{result=(Just r), resultPaths=(Just rp), document=(Just doc), ..} =+ it name $ do+ query selector doc `shouldBe` Right r+ queryLocated selector doc `shouldBe` Right (V.zip rp r)++-- if result is non-deterministic (any json from the list of results)+runTestCase TestCase{results=(Just rs), resultsPaths=(Just rsp), document=(Just doc), ..} = do+ it name $ do+ query selector doc `shouldSatisfy` (\x -> fromRight V.empty x `elem` rs)+ queryLocated selector doc `shouldSatisfy` (\x -> fromRight V.empty x `elem` vecList)+ where+ vecList = [ V.zip rp r | rp <- rsp, r <- rs]++runTestCase _ = pure ()
+ test/compliance/Main.hs view
@@ -0,0 +1,39 @@+module Main+ ( main )+ where++import qualified Data.Aeson as JSON+import qualified Test.Hspec as HS+import qualified Data.Text.Encoding as T+import qualified Data.Text.IO as TIO++import Data.Either (fromRight)++import qualified ComplianceSpec+import qualified Paths_aeson_jsonpath as Paths++import ComplianceSpec (TestSuite (..))++import Test.Hspec.Runner+import Prelude++compliance :: Either String TestSuite -> Spec+compliance cts = do+ HS.describe "Run compliance tests" $+ ComplianceSpec.spec (fromRight TestSuite{tests=[]} cts)++readCtsFile :: FilePath -> IO (Either String TestSuite)+readCtsFile filePath = do+ contents <- TIO.readFile filePath+ return $ JSON.eitherDecodeStrict' $ T.encodeUtf8 contents++main :: IO ()+main = do+ file <- Paths.getDataFileName "jsonpath-compliance-test-suite/cts.json"+ cts <- readCtsFile file+ summary <- hspecWithResult defaultConfig + { configColorMode = ColorAuto+ } (compliance cts)+ + putStrLn $ "Total tests: " ++ show (summaryExamples summary)+ putStrLn $ "Failures: " ++ show (summaryFailures summary)
− test/cts.json
@@ -1,10941 +0,0 @@-{- "description": "JSONPath Compliance Test Suite. This file is autogenerated, do not edit.",- "tests": [- {- "name": "basic, root",- "selector": "$",- "document": [- "first",- "second"- ],- "result": [- [- "first",- "second"- ]- ]- },- {- "name": "basic, no leading whitespace",- "selector": " $",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "basic, no trailing whitespace",- "selector": "$ ",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "basic, name shorthand",- "selector": "$.a",- "document": {- "a": "A",- "b": "B"- },- "result": [- "A"- ]- },- {- "name": "basic, name shorthand, extended unicode ☺",- "selector": "$.☺",- "document": {- "☺": "A",- "b": "B"- },- "result": [- "A"- ]- },- {- "name": "basic, name shorthand, underscore",- "selector": "$._",- "document": {- "_": "A",- "_foo": "B"- },- "result": [- "A"- ]- },- {- "name": "basic, name shorthand, symbol",- "selector": "$.&",- "invalid_selector": true- },- {- "name": "basic, name shorthand, number",- "selector": "$.1",- "invalid_selector": true- },- {- "name": "basic, name shorthand, absent data",- "selector": "$.c",- "document": {- "a": "A",- "b": "B"- },- "result": []- },- {- "name": "basic, name shorthand, array data",- "selector": "$.a",- "document": [- "first",- "second"- ],- "result": []- },- {- "name": "basic, wildcard shorthand, object data",- "selector": "$.*",- "document": {- "a": "A",- "b": "B"- },- "results": [- [- "A",- "B"- ],- [- "B",- "A"- ]- ]- },- {- "name": "basic, wildcard shorthand, array data",- "selector": "$.*",- "document": [- "first",- "second"- ],- "result": [- "first",- "second"- ]- },- {- "name": "basic, wildcard selector, array data",- "selector": "$[*]",- "document": [- "first",- "second"- ],- "result": [- "first",- "second"- ]- },- {- "name": "basic, wildcard shorthand, then name shorthand",- "selector": "$.*.a",- "document": {- "x": {- "a": "Ax",- "b": "Bx"- },- "y": {- "a": "Ay",- "b": "By"- }- },- "results": [- [- "Ax",- "Ay"- ],- [- "Ay",- "Ax"- ]- ]- },- {- "name": "basic, multiple selectors",- "selector": "$[0,2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0,- 2- ]- },- {- "name": "basic, multiple selectors, space instead of comma",- "selector": "$[0 2]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "basic, selector, leading comma",- "selector": "$[,0]",- "invalid_selector": true- },- {- "name": "basic, selector, trailing comma",- "selector": "$[0,]",- "invalid_selector": true- },- {- "name": "basic, multiple selectors, name and index, array data",- "selector": "$['a',1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1- ]- },- {- "name": "basic, multiple selectors, name and index, object data",- "selector": "$['a',1]",- "document": {- "a": 1,- "b": 2- },- "result": [- 1- ]- },- {- "name": "basic, multiple selectors, index and slice",- "selector": "$[1,5:7]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1,- 5,- 6- ]- },- {- "name": "basic, multiple selectors, index and slice, overlapping",- "selector": "$[1,0:3]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1,- 0,- 1,- 2- ]- },- {- "name": "basic, multiple selectors, duplicate index",- "selector": "$[1,1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1,- 1- ]- },- {- "name": "basic, multiple selectors, wildcard and index",- "selector": "$[*,1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9,- 1- ]- },- {- "name": "basic, multiple selectors, wildcard and name",- "selector": "$[*,'a']",- "document": {- "a": "A",- "b": "B"- },- "results": [- [- "A",- "B",- "A"- ],- [- "B",- "A",- "A"- ]- ]- },- {- "name": "basic, multiple selectors, wildcard and slice",- "selector": "$[*,0:2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9,- 0,- 1- ]- },- {- "name": "basic, multiple selectors, multiple wildcards",- "selector": "$[*,*]",- "document": [- 0,- 1,- 2- ],- "result": [- 0,- 1,- 2,- 0,- 1,- 2- ]- },- {- "name": "basic, empty segment",- "selector": "$[]",- "invalid_selector": true- },- {- "name": "basic, descendant segment, index",- "selector": "$..[1]",- "document": {- "o": [- 0,- 1,- [- 2,- 3- ]- ]- },- "result": [- 1,- 3- ]- },- {- "name": "basic, descendant segment, name shorthand",- "selector": "$..a",- "document": {- "o": [- {- "a": "b"- },- {- "a": "c"- }- ]- },- "result": [- "b",- "c"- ]- },- {- "name": "basic, descendant segment, wildcard shorthand, array data",- "selector": "$..*",- "document": [- 0,- 1- ],- "result": [- 0,- 1- ]- },- {- "name": "basic, descendant segment, wildcard selector, array data",- "selector": "$..[*]",- "document": [- 0,- 1- ],- "result": [- 0,- 1- ]- },- {- "name": "basic, descendant segment, wildcard selector, nested arrays",- "selector": "$..[*]",- "document": [- [- [- 1- ]- ],- [- 2- ]- ],- "results": [- [- [- [- 1- ]- ],- [- 2- ],- [- 1- ],- 1,- 2- ],- [- [- [- 1- ]- ],- [- 2- ],- [- 1- ],- 2,- 1- ]- ]- },- {- "name": "basic, descendant segment, wildcard selector, nested objects",- "selector": "$..[*]",- "document": {- "a": {- "c": {- "e": 1- }- },- "b": {- "d": 2- }- },- "results": [- [- {- "c": {- "e": 1- }- },- {- "d": 2- },- {- "e": 1- },- 1,- 2- ],- [- {- "c": {- "e": 1- }- },- {- "d": 2- },- {- "e": 1- },- 2,- 1- ],- [- {- "c": {- "e": 1- }- },- {- "d": 2- },- 2,- {- "e": 1- },- 1- ],- [- {- "d": 2- },- {- "c": {- "e": 1- }- },- {- "e": 1- },- 1,- 2- ],- [- {- "d": 2- },- {- "c": {- "e": 1- }- },- {- "e": 1- },- 2,- 1- ],- [- {- "d": 2- },- {- "c": {- "e": 1- }- },- 2,- {- "e": 1- },- 1- ]- ]- },- {- "name": "basic, descendant segment, wildcard shorthand, object data",- "selector": "$..*",- "document": {- "a": "b"- },- "result": [- "b"- ]- },- {- "name": "basic, descendant segment, wildcard shorthand, nested data",- "selector": "$..*",- "document": {- "o": [- {- "a": "b"- }- ]- },- "result": [- [- {- "a": "b"- }- ],- {- "a": "b"- },- "b"- ]- },- {- "name": "basic, descendant segment, multiple selectors",- "selector": "$..['a','d']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- "b",- "e",- "c",- "f"- ]- },- {- "name": "basic, descendant segment, object traversal, multiple selectors",- "selector": "$..['a','d']",- "document": {- "x": {- "a": "b",- "d": "e"- },- "y": {- "a": "c",- "d": "f"- }- },- "results": [- [- "b",- "e",- "c",- "f"- ],- [- "c",- "f",- "b",- "e"- ]- ]- },- {- "name": "basic, bald descendant segment",- "selector": "$..",- "invalid_selector": true- },- {- "name": "filter, existence, without segments",- "selector": "$[?@]",- "document": {- "a": 1,- "b": null- },- "results": [- [- 1,- null- ],- [- null,- 1- ]- ]- },- {- "name": "filter, existence",- "selector": "$[?@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ]- },- {- "name": "filter, existence, present with null",- "selector": "$[?@.a]",- "document": [- {- "a": null,- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": null,- "d": "e"- }- ]- },- {- "name": "filter, absolute existence, without segments",- "selector": "$[?$]",- "document": {- "a": 1,- "b": null- },- "results": [- [- 1,- null- ],- [- null,- 1- ]- ]- },- {- "name": "filter, absolute existence, with segments",- "selector": "$[?$.*.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ]- },- {- "name": "filter, equals string, single quotes",- "selector": "$[?@.a=='b']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ]- },- {- "name": "filter, equals numeric string, single quotes",- "selector": "$[?@.a=='1']",- "document": [- {- "a": "1",- "d": "e"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": "1",- "d": "e"- }- ]- },- {- "name": "filter, equals string, double quotes",- "selector": "$[?@.a==\"b\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ]- },- {- "name": "filter, equals numeric string, double quotes",- "selector": "$[?@.a==\"1\"]",- "document": [- {- "a": "1",- "d": "e"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": "1",- "d": "e"- }- ]- },- {- "name": "filter, equals number",- "selector": "$[?@.a==1]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, equals null",- "selector": "$[?@.a==null]",- "document": [- {- "a": null,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": null,- "d": "e"- }- ]- },- {- "name": "filter, equals null, absent from data",- "selector": "$[?@.a==null]",- "document": [- {- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, equals true",- "selector": "$[?@.a==true]",- "document": [- {- "a": true,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": true,- "d": "e"- }- ]- },- {- "name": "filter, equals false",- "selector": "$[?@.a==false]",- "document": [- {- "a": false,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": false,- "d": "e"- }- ]- },- {- "name": "filter, equals self",- "selector": "$[?@==@]",- "document": [- 1,- null,- true,- {- "a": "b"- },- [- false- ]- ],- "result": [- 1,- null,- true,- {- "a": "b"- },- [- false- ]- ]- },- {- "name": "filter, absolute, equals self",- "selector": "$[?$==$]",- "document": [- 1,- null,- true,- {- "a": "b"- },- [- false- ]- ],- "result": [- 1,- null,- true,- {- "a": "b"- },- [- false- ]- ]- },- {- "name": "filter, deep equality, arrays",- "selector": "$[?@.a==@.b]",- "document": [- {- "a": false,- "b": [- 1,- 2- ]- },- {- "a": [- [- 1,- [- 2- ]- ]- ],- "b": [- [- 1,- [- 2- ]- ]- ]- },- {- "a": [- [- 1,- [- 2- ]- ]- ],- "b": [- [- [- 2- ],- 1- ]- ]- },- {- "a": [- [- 1,- [- 2- ]- ]- ],- "b": [- [- 1,- 2- ]- ]- }- ],- "result": [- {- "a": [- [- 1,- [- 2- ]- ]- ],- "b": [- [- 1,- [- 2- ]- ]- ]- }- ]- },- {- "name": "filter, deep equality, objects",- "selector": "$[?@.a==@.b]",- "document": [- {- "a": false,- "b": {- "x": 1,- "y": {- "z": 1- }- }- },- {- "a": {- "x": 1,- "y": {- "z": 1- }- },- "b": {- "x": 1,- "y": {- "z": 1- }- }- },- {- "a": {- "x": 1,- "y": {- "z": 1- }- },- "b": {- "y": {- "z": 1- },- "x": 1- }- },- {- "a": {- "x": 1,- "y": {- "z": 1- }- },- "b": {- "x": 1- }- },- {- "a": {- "x": 1,- "y": {- "z": 1- }- },- "b": {- "x": 1,- "y": {- "z": 2- }- }- }- ],- "result": [- {- "a": {- "x": 1,- "y": {- "z": 1- }- },- "b": {- "x": 1,- "y": {- "z": 1- }- }- },- {- "a": {- "x": 1,- "y": {- "z": 1- }- },- "b": {- "y": {- "z": 1- },- "x": 1- }- }- ]- },- {- "name": "filter, not-equals string, single quotes",- "selector": "$[?@.a!='b']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, not-equals numeric string, single quotes",- "selector": "$[?@.a!='1']",- "document": [- {- "a": "1",- "d": "e"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "f"- }- ]- },- {- "name": "filter, not-equals string, single quotes, different type",- "selector": "$[?@.a!='b']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "f"- }- ]- },- {- "name": "filter, not-equals string, double quotes",- "selector": "$[?@.a!=\"b\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, not-equals numeric string, double quotes",- "selector": "$[?@.a!=\"1\"]",- "document": [- {- "a": "1",- "d": "e"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "f"- }- ]- },- {- "name": "filter, not-equals string, double quotes, different types",- "selector": "$[?@.a!=\"b\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "f"- }- ]- },- {- "name": "filter, not-equals number",- "selector": "$[?@.a!=1]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "f"- }- ],- "result": [- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "f"- }- ]- },- {- "name": "filter, not-equals number, different types",- "selector": "$[?@.a!=1]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, not-equals null",- "selector": "$[?@.a!=null]",- "document": [- {- "a": null,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, not-equals null, absent from data",- "selector": "$[?@.a!=null]",- "document": [- {- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "d": "e"- },- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, not-equals true",- "selector": "$[?@.a!=true]",- "document": [- {- "a": true,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, not-equals false",- "selector": "$[?@.a!=false]",- "document": [- {- "a": false,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, less than string, single quotes",- "selector": "$[?@.a<'c']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ]- },- {- "name": "filter, less than string, double quotes",- "selector": "$[?@.a<\"c\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ]- },- {- "name": "filter, less than number",- "selector": "$[?@.a<10]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 10,- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": 20,- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, less than null",- "selector": "$[?@.a<null]",- "document": [- {- "a": null,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, less than true",- "selector": "$[?@.a<true]",- "document": [- {- "a": true,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, less than false",- "selector": "$[?@.a<false]",- "document": [- {- "a": false,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, less than or equal to string, single quotes",- "selector": "$[?@.a<='c']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, less than or equal to string, double quotes",- "selector": "$[?@.a<=\"c\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, less than or equal to number",- "selector": "$[?@.a<=10]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 10,- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": 20,- "d": "f"- }- ],- "result": [- {- "a": 1,- "d": "e"- },- {- "a": 10,- "d": "e"- }- ]- },- {- "name": "filter, less than or equal to null",- "selector": "$[?@.a<=null]",- "document": [- {- "a": null,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": null,- "d": "e"- }- ]- },- {- "name": "filter, less than or equal to true",- "selector": "$[?@.a<=true]",- "document": [- {- "a": true,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": true,- "d": "e"- }- ]- },- {- "name": "filter, less than or equal to false",- "selector": "$[?@.a<=false]",- "document": [- {- "a": false,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": false,- "d": "e"- }- ]- },- {- "name": "filter, greater than string, single quotes",- "selector": "$[?@.a>'c']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "d",- "d": "f"- }- ]- },- {- "name": "filter, greater than string, double quotes",- "selector": "$[?@.a>\"c\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "d",- "d": "f"- }- ]- },- {- "name": "filter, greater than number",- "selector": "$[?@.a>10]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 10,- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": 20,- "d": "f"- }- ],- "result": [- {- "a": 20,- "d": "f"- }- ]- },- {- "name": "filter, greater than null",- "selector": "$[?@.a>null]",- "document": [- {- "a": null,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, greater than true",- "selector": "$[?@.a>true]",- "document": [- {- "a": true,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, greater than false",- "selector": "$[?@.a>false]",- "document": [- {- "a": false,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": []- },- {- "name": "filter, greater than or equal to string, single quotes",- "selector": "$[?@.a>='c']",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ]- },- {- "name": "filter, greater than or equal to string, double quotes",- "selector": "$[?@.a>=\"c\"]",- "document": [- {- "a": "b",- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ]- },- {- "name": "filter, greater than or equal to number",- "selector": "$[?@.a>=10]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 10,- "d": "e"- },- {- "a": "c",- "d": "f"- },- {- "a": 20,- "d": "f"- }- ],- "result": [- {- "a": 10,- "d": "e"- },- {- "a": 20,- "d": "f"- }- ]- },- {- "name": "filter, greater than or equal to null",- "selector": "$[?@.a>=null]",- "document": [- {- "a": null,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": null,- "d": "e"- }- ]- },- {- "name": "filter, greater than or equal to true",- "selector": "$[?@.a>=true]",- "document": [- {- "a": true,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": true,- "d": "e"- }- ]- },- {- "name": "filter, greater than or equal to false",- "selector": "$[?@.a>=false]",- "document": [- {- "a": false,- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": false,- "d": "e"- }- ]- },- {- "name": "filter, exists and not-equals null, absent from data",- "selector": "$[?@.a&&@.a!=null]",- "document": [- {- "d": "e"- },- {- "a": "c",- "d": "f"- }- ],- "result": [- {- "a": "c",- "d": "f"- }- ]- },- {- "name": "filter, exists and exists, data false",- "selector": "$[?@.a&&@.b]",- "document": [- {- "a": false,- "b": false- },- {- "b": false- },- {- "c": false- }- ],- "result": [- {- "a": false,- "b": false- }- ]- },- {- "name": "filter, exists or exists, data false",- "selector": "$[?@.a||@.b]",- "document": [- {- "a": false,- "b": false- },- {- "b": false- },- {- "c": false- }- ],- "result": [- {- "a": false,- "b": false- },- {- "b": false- }- ]- },- {- "name": "filter, and",- "selector": "$[?@.a>0&&@.a<10]",- "document": [- {- "a": -10,- "d": "e"- },- {- "a": 5,- "d": "f"- },- {- "a": 20,- "d": "f"- }- ],- "result": [- {- "a": 5,- "d": "f"- }- ]- },- {- "name": "filter, or",- "selector": "$[?@.a=='b'||@.a=='d']",- "document": [- {- "a": "a",- "d": "e"- },- {- "a": "b",- "d": "f"- },- {- "a": "c",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ]- },- {- "name": "filter, not expression",- "selector": "$[?!(@.a=='b')]",- "document": [- {- "a": "a",- "d": "e"- },- {- "a": "b",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "a",- "d": "e"- },- {- "a": "d",- "d": "f"- }- ]- },- {- "name": "filter, not exists",- "selector": "$[?!@.a]",- "document": [- {- "a": "a",- "d": "e"- },- {- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "d": "f"- }- ]- },- {- "name": "filter, not exists, data null",- "selector": "$[?!@.a]",- "document": [- {- "a": null,- "d": "e"- },- {- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "d": "f"- }- ]- },- {- "name": "filter, non-singular existence, wildcard",- "selector": "$[?@.*]",- "document": [- 1,- [],- [- 2- ],- {},- {- "a": 3- }- ],- "result": [- [- 2- ],- {- "a": 3- }- ]- },- {- "name": "filter, non-singular existence, multiple",- "selector": "$[?@[0, 0, 'a']]",- "document": [- 1,- [],- [- 2- ],- [- 2,- 3- ],- {- "a": 3- },- {- "b": 4- },- {- "a": 3,- "b": 4- }- ],- "result": [- [- 2- ],- [- 2,- 3- ],- {- "a": 3- },- {- "a": 3,- "b": 4- }- ]- },- {- "name": "filter, non-singular existence, slice",- "selector": "$[?@[0:2]]",- "document": [- 1,- [],- [- 2- ],- [- 2,- 3,- 4- ],- {},- {- "a": 3- }- ],- "result": [- [- 2- ],- [- 2,- 3,- 4- ]- ]- },- {- "name": "filter, non-singular existence, negated",- "selector": "$[?!@.*]",- "document": [- 1,- [],- [- 2- ],- {},- {- "a": 3- }- ],- "result": [- 1,- [],- {}- ]- },- {- "name": "filter, non-singular query in comparison, slice",- "selector": "$[?@[0:0]==0]",- "invalid_selector": true- },- {- "name": "filter, non-singular query in comparison, all children",- "selector": "$[?@[*]==0]",- "invalid_selector": true- },- {- "name": "filter, non-singular query in comparison, descendants",- "selector": "$[?@..a==0]",- "invalid_selector": true- },- {- "name": "filter, non-singular query in comparison, combined",- "selector": "$[?@.a[*].a==0]",- "invalid_selector": true- },- {- "name": "filter, nested",- "selector": "$[?@[?@>1]]",- "document": [- [- 0- ],- [- 0,- 1- ],- [- 0,- 1,- 2- ],- [- 42- ]- ],- "result": [- [- 0,- 1,- 2- ],- [- 42- ]- ]- },- {- "name": "filter, name segment on primitive, selects nothing",- "selector": "$[?@.a == 1]",- "document": {- "a": 1- },- "result": []- },- {- "name": "filter, name segment on array, selects nothing",- "selector": "$[?@['0'] == 5]",- "document": [- [- 5,- 6- ]- ],- "result": []- },- {- "name": "filter, index segment on object, selects nothing",- "selector": "$[?@[0] == 5]",- "document": [- {- "0": 5- }- ],- "result": []- },- {- "name": "filter, relative non-singular query, index, equal",- "selector": "$[?(@[0, 0]==42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, index, not equal",- "selector": "$[?(@[0, 0]!=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, index, less-or-equal",- "selector": "$[?(@[0, 0]<=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, name, equal",- "selector": "$[?(@['a', 'a']==42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, name, not equal",- "selector": "$[?(@['a', 'a']!=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, name, less-or-equal",- "selector": "$[?(@['a', 'a']<=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, combined, equal",- "selector": "$[?(@[0, '0']==42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, combined, not equal",- "selector": "$[?(@[0, '0']!=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, combined, less-or-equal",- "selector": "$[?(@[0, '0']<=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, relative non-singular query, wildcard, equal",- "selector": "$[?(@.*==42)]",- "invalid_selector": true- },- {- "name": "filter, relative non-singular query, wildcard, not equal",- "selector": "$[?(@.*!=42)]",- "invalid_selector": true- },- {- "name": "filter, relative non-singular query, wildcard, less-or-equal",- "selector": "$[?(@.*<=42)]",- "invalid_selector": true- },- {- "name": "filter, relative non-singular query, slice, equal",- "selector": "$[?(@[0:0]==42)]",- "invalid_selector": true- },- {- "name": "filter, relative non-singular query, slice, not equal",- "selector": "$[?(@[0:0]!=42)]",- "invalid_selector": true- },- {- "name": "filter, relative non-singular query, slice, less-or-equal",- "selector": "$[?(@[0:0]<=42)]",- "invalid_selector": true- },- {- "name": "filter, absolute non-singular query, index, equal",- "selector": "$[?($[0, 0]==42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, index, not equal",- "selector": "$[?($[0, 0]!=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, index, less-or-equal",- "selector": "$[?($[0, 0]<=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, name, equal",- "selector": "$[?($['a', 'a']==42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, name, not equal",- "selector": "$[?($['a', 'a']!=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, name, less-or-equal",- "selector": "$[?($['a', 'a']<=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, combined, equal",- "selector": "$[?($[0, '0']==42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, combined, not equal",- "selector": "$[?($[0, '0']!=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, combined, less-or-equal",- "selector": "$[?($[0, '0']<=42)]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, absolute non-singular query, wildcard, equal",- "selector": "$[?($.*==42)]",- "invalid_selector": true- },- {- "name": "filter, absolute non-singular query, wildcard, not equal",- "selector": "$[?($.*!=42)]",- "invalid_selector": true- },- {- "name": "filter, absolute non-singular query, wildcard, less-or-equal",- "selector": "$[?($.*<=42)]",- "invalid_selector": true- },- {- "name": "filter, absolute non-singular query, slice, equal",- "selector": "$[?($[0:0]==42)]",- "invalid_selector": true- },- {- "name": "filter, absolute non-singular query, slice, not equal",- "selector": "$[?($[0:0]!=42)]",- "invalid_selector": true- },- {- "name": "filter, absolute non-singular query, slice, less-or-equal",- "selector": "$[?($[0:0]<=42)]",- "invalid_selector": true- },- {- "name": "filter, multiple selectors",- "selector": "$[?@.a,?@.b]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ]- },- {- "name": "filter, multiple selectors, comparison",- "selector": "$[?@.a=='b',?@.b=='x']",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ]- },- {- "name": "filter, multiple selectors, overlapping",- "selector": "$[?@.a,?@.d]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ]- },- {- "name": "filter, multiple selectors, filter and index",- "selector": "$[?@.a,1]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ]- },- {- "name": "filter, multiple selectors, filter and wildcard",- "selector": "$[?@.a,*]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ]- },- {- "name": "filter, multiple selectors, filter and slice",- "selector": "$[?@.a,1:]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- },- {- "g": "h"- }- ],- "result": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- },- {- "g": "h"- }- ]- },- {- "name": "filter, multiple selectors, comparison filter, index and slice",- "selector": "$[1, ?@.a=='b', 1:]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "b": "c",- "d": "f"- },- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, equals number, zero and negative zero",- "selector": "$[?@.a==0]",- "document": [- {- "a": 0,- "d": "e"- },- {- "a": 0.1,- "d": "f"- },- {- "a": "0",- "d": "g"- }- ],- "result": [- {- "a": 0,- "d": "e"- }- ]- },- {- "name": "filter, equals number, negative zero and zero",- "selector": "$[?@.a==-0]",- "document": [- {- "a": 0,- "d": "e"- },- {- "a": 0.1,- "d": "f"- },- {- "a": "0",- "d": "g"- }- ],- "result": [- {- "a": 0,- "d": "e"- }- ]- },- {- "name": "filter, equals number, with and without decimal fraction",- "selector": "$[?@.a==1.0]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "g"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent",- "selector": "$[?@.a==1e2]",- "document": [- {- "a": 100,- "d": "e"- },- {- "a": 100.1,- "d": "f"- },- {- "a": "100",- "d": "g"- }- ],- "result": [- {- "a": 100,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent upper e",- "selector": "$[?@.a==1E2]",- "document": [- {- "a": 100,- "d": "e"- },- {- "a": 100.1,- "d": "f"- },- {- "a": "100",- "d": "g"- }- ],- "result": [- {- "a": 100,- "d": "e"- }- ]- },- {- "name": "filter, equals number, positive exponent",- "selector": "$[?@.a==1e+2]",- "document": [- {- "a": 100,- "d": "e"- },- {- "a": 100.1,- "d": "f"- },- {- "a": "100",- "d": "g"- }- ],- "result": [- {- "a": 100,- "d": "e"- }- ]- },- {- "name": "filter, equals number, negative exponent",- "selector": "$[?@.a==1e-2]",- "document": [- {- "a": 0.01,- "d": "e"- },- {- "a": 0.02,- "d": "f"- },- {- "a": "0.01",- "d": "g"- }- ],- "result": [- {- "a": 0.01,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent 0",- "selector": "$[?@.a==1e0]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "g"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent -0",- "selector": "$[?@.a==1e-0]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "g"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent +0",- "selector": "$[?@.a==1e+0]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "g"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent leading -0",- "selector": "$[?@.a==1e-02]",- "document": [- {- "a": 0.01,- "d": "e"- },- {- "a": 0.02,- "d": "f"- },- {- "a": "0.01",- "d": "g"- }- ],- "result": [- {- "a": 0.01,- "d": "e"- }- ]- },- {- "name": "filter, equals number, exponent +00",- "selector": "$[?@.a==1e+00]",- "document": [- {- "a": 1,- "d": "e"- },- {- "a": 2,- "d": "f"- },- {- "a": "1",- "d": "g"- }- ],- "result": [- {- "a": 1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, decimal fraction",- "selector": "$[?@.a==1.1]",- "document": [- {- "a": 1.1,- "d": "e"- },- {- "a": 1,- "d": "f"- },- {- "a": "1.1",- "d": "g"- }- ],- "result": [- {- "a": 1.1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, decimal fraction, trailing 0",- "selector": "$[?@.a==1.10]",- "document": [- {- "a": 1.1,- "d": "e"- },- {- "a": 1,- "d": "f"- },- {- "a": "1.1",- "d": "g"- }- ],- "result": [- {- "a": 1.1,- "d": "e"- }- ]- },- {- "name": "filter, equals number, decimal fraction, exponent",- "selector": "$[?@.a==1.1e2]",- "document": [- {- "a": 110,- "d": "e"- },- {- "a": 110.1,- "d": "f"- },- {- "a": "110",- "d": "g"- }- ],- "result": [- {- "a": 110,- "d": "e"- }- ]- },- {- "name": "filter, equals number, decimal fraction, positive exponent",- "selector": "$[?@.a==1.1e+2]",- "document": [- {- "a": 110,- "d": "e"- },- {- "a": 110.1,- "d": "f"- },- {- "a": "110",- "d": "g"- }- ],- "result": [- {- "a": 110,- "d": "e"- }- ]- },- {- "name": "filter, equals number, decimal fraction, negative exponent",- "selector": "$[?@.a==1.1e-2]",- "document": [- {- "a": 0.011,- "d": "e"- },- {- "a": 0.012,- "d": "f"- },- {- "a": "0.011",- "d": "g"- }- ],- "result": [- {- "a": 0.011,- "d": "e"- }- ]- },- {- "name": "filter, equals number, invalid plus",- "selector": "$[?@.a==+1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid minus space",- "selector": "$[?@.a==- 1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid double minus",- "selector": "$[?@.a==--1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid no int digit",- "selector": "$[?@.a==.1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid minus no int digit",- "selector": "$[?@.a==-.1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid 00",- "selector": "$[?@.a==00]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid leading 0",- "selector": "$[?@.a==01]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid no fractional digit",- "selector": "$[?@.a==1.]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid middle minus",- "selector": "$[?@.a==1.-1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid no fractional digit e",- "selector": "$[?@.a==1.e1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid no e digit",- "selector": "$[?@.a==1e]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid no e digit minus",- "selector": "$[?@.a==1e-]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid double e",- "selector": "$[?@.a==1eE1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid e digit double minus",- "selector": "$[?@.a==1e--1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid e digit plus minus",- "selector": "$[?@.a==1e+-1]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid e decimal",- "selector": "$[?@.a==1e2.3]",- "invalid_selector": true- },- {- "name": "filter, equals number, invalid multi e",- "selector": "$[?@.a==1e2e3]",- "invalid_selector": true- },- {- "name": "filter, equals, special nothing",- "selector": "$.values[?length(@.a) == value($..c)]",- "document": {- "c": "cd",- "values": [- {- "a": "ab"- },- {- "c": "d"- },- {- "a": null- }- ]- },- "result": [- {- "c": "d"- },- {- "a": null- }- ],- "tags": [- "function"- ]- },- {- "name": "filter, equals, empty node list and empty node list",- "selector": "$[?@.a == @.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "c": 3- }- ]- },- {- "name": "filter, equals, empty node list and special nothing",- "selector": "$[?@.a == length(@.b)]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "b": 2- },- {- "c": 3- }- ],- "tags": [- "function",- "whitespace"- ]- },- {- "name": "filter, object data",- "selector": "$[?@<3]",- "document": {- "a": 1,- "b": 2,- "c": 3- },- "results": [- [- 1,- 2- ],- [- 2,- 1- ]- ]- },- {- "name": "filter, and binds more tightly than or",- "selector": "$[?@.a || @.b && @.c]",- "document": [- {- "a": 1- },- {- "b": 2,- "c": 3- },- {- "c": 3- },- {- "b": 2- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2,- "c": 3- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, left to right evaluation",- "selector": "$[?@.a && @.b || @.c]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- },- {- "a": 1,- "c": 3- },- {- "b": 1,- "c": 3- },- {- "c": 3- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "result": [- {- "a": 1,- "b": 2- },- {- "a": 1,- "c": 3- },- {- "b": 1,- "c": 3- },- {- "c": 3- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, group terms, left",- "selector": "$[?(@.a || @.b) && @.c]",- "document": [- {- "a": 1,- "b": 2- },- {- "a": 1,- "c": 3- },- {- "b": 2,- "c": 3- },- {- "a": 1- },- {- "b": 2- },- {- "c": 3- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "result": [- {- "a": 1,- "c": 3- },- {- "b": 2,- "c": 3- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, group terms, right",- "selector": "$[?@.a && (@.b || @.c)]",- "document": [- {- "a": 1- },- {- "a": 1,- "b": 2- },- {- "a": 1,- "c": 2- },- {- "b": 2- },- {- "c": 2- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "result": [- {- "a": 1,- "b": 2- },- {- "a": 1,- "c": 2- },- {- "a": 1,- "b": 2,- "c": 3- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, string literal, single quote in double quotes",- "selector": "$[?@ == \"quoted' literal\"]",- "document": [- "quoted' literal",- "a",- "quoted\\' literal"- ],- "result": [- "quoted' literal"- ]- },- {- "name": "filter, string literal, double quote in single quotes",- "selector": "$[?@ == 'quoted\" literal']",- "document": [- "quoted\" literal",- "a",- "quoted\\\" literal",- "'quoted\" literal'"- ],- "result": [- "quoted\" literal"- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, string literal, escaped single quote in single quotes",- "selector": "$[?@ == 'quoted\\' literal']",- "document": [- "quoted' literal",- "a",- "quoted\\' literal",- "'quoted\" literal'"- ],- "result": [- "quoted' literal"- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, string literal, escaped double quote in double quotes",- "selector": "$[?@ == \"quoted\\\" literal\"]",- "document": [- "quoted\" literal",- "a",- "quoted\\\" literal",- "'quoted\" literal'"- ],- "result": [- "quoted\" literal"- ],- "tags": [- "whitespace"- ]- },- {- "name": "filter, literal true must be compared",- "selector": "$[?true]",- "invalid_selector": true- },- {- "name": "filter, literal false must be compared",- "selector": "$[?false]",- "invalid_selector": true- },- {- "name": "filter, literal string must be compared",- "selector": "$[?'abc']",- "invalid_selector": true- },- {- "name": "filter, literal int must be compared",- "selector": "$[?2]",- "invalid_selector": true- },- {- "name": "filter, literal float must be compared",- "selector": "$[?2.2]",- "invalid_selector": true- },- {- "name": "filter, literal null must be compared",- "selector": "$[?null]",- "invalid_selector": true- },- {- "name": "filter, and, literals must be compared",- "selector": "$[?true && false]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, or, literals must be compared",- "selector": "$[?true || false]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, and, right hand literal must be compared",- "selector": "$[?true == false && false]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, or, right hand literal must be compared",- "selector": "$[?true == false || false]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, and, left hand literal must be compared",- "selector": "$[?false && true == false]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, or, left hand literal must be compared",- "selector": "$[?false || true == false]",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "filter, true, incorrectly capitalized",- "selector": "$[?@==True]",- "invalid_selector": true,- "tags": [- "case"- ]- },- {- "name": "filter, false, incorrectly capitalized",- "selector": "$[?@==False]",- "invalid_selector": true,- "tags": [- "case"- ]- },- {- "name": "filter, null, incorrectly capitalized",- "selector": "$[?@==Null]",- "invalid_selector": true,- "tags": [- "case"- ]- },- {- "name": "index selector, first element",- "selector": "$[0]",- "document": [- "first",- "second"- ],- "result": [- "first"- ],- "tags": [- "index"- ]- },- {- "name": "index selector, second element",- "selector": "$[1]",- "document": [- "first",- "second"- ],- "result": [- "second"- ],- "tags": [- "index"- ]- },- {- "name": "index selector, out of bound",- "selector": "$[2]",- "document": [- "first",- "second"- ],- "result": [],- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, min exact index",- "selector": "$[-9007199254740991]",- "document": [- "first",- "second"- ],- "result": [],- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, max exact index",- "selector": "$[9007199254740991]",- "document": [- "first",- "second"- ],- "result": [],- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, min exact index - 1",- "selector": "$[-9007199254740992]",- "invalid_selector": true,- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, max exact index + 1",- "selector": "$[9007199254740992]",- "invalid_selector": true,- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, overflowing index",- "selector": "$[231584178474632390847141970017375815706539969331281128078915168015826259279872]",- "invalid_selector": true,- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, not actually an index, overflowing index leads into general text",- "selector": "$[231584178474632390847141970017375815706539969331281128078915168SomeRandomText]",- "invalid_selector": true,- "tags": [- "index"- ]- },- {- "name": "index selector, negative",- "selector": "$[-1]",- "document": [- "first",- "second"- ],- "result": [- "second"- ],- "tags": [- "index"- ]- },- {- "name": "index selector, more negative",- "selector": "$[-2]",- "document": [- "first",- "second"- ],- "result": [- "first"- ],- "tags": [- "index"- ]- },- {- "name": "index selector, negative out of bound",- "selector": "$[-3]",- "document": [- "first",- "second"- ],- "result": [],- "tags": [- "boundary",- "index"- ]- },- {- "name": "index selector, on object",- "selector": "$[0]",- "document": {- "foo": 1- },- "result": [],- "tags": [- "index"- ]- },- {- "name": "index selector, leading 0",- "selector": "$[01]",- "invalid_selector": true,- "tags": [- "index"- ]- },- {- "name": "index selector, decimal",- "selector": "$[1.0]",- "invalid_selector": true,- "tags": [- "index"- ]- },- {- "name": "index selector, plus",- "selector": "$[+1]",- "invalid_selector": true,- "tags": [- "index"- ]- },- {- "name": "index selector, minus space",- "selector": "$[- 1]",- "invalid_selector": true,- "tags": [- "index",- "whitespace"- ]- },- {- "name": "index selector, -0",- "selector": "$[-0]",- "invalid_selector": true,- "tags": [- "index"- ]- },- {- "name": "index selector, leading -0",- "selector": "$[-01]",- "invalid_selector": true,- "tags": [- "index"- ]- },- {- "name": "name selector, double quotes",- "selector": "$[\"a\"]",- "document": {- "a": "A",- "b": "B"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, absent data",- "selector": "$[\"c\"]",- "document": {- "a": "A",- "b": "B"- },- "result": []- },- {- "name": "name selector, double quotes, array data",- "selector": "$[\"a\"]",- "document": [- "first",- "second"- ],- "result": []- },- {- "name": "name selector, double quotes, embedded U+0000",- "selector": "$[\"\u0000\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0001",- "selector": "$[\"\u0001\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0002",- "selector": "$[\"\u0002\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0003",- "selector": "$[\"\u0003\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0004",- "selector": "$[\"\u0004\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0005",- "selector": "$[\"\u0005\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0006",- "selector": "$[\"\u0006\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0007",- "selector": "$[\"\u0007\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0008",- "selector": "$[\"\b\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0009",- "selector": "$[\"\t\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+000A",- "selector": "$[\"\n\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+000B",- "selector": "$[\"\u000b\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+000C",- "selector": "$[\"\f\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+000D",- "selector": "$[\"\r\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+000E",- "selector": "$[\"\u000e\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+000F",- "selector": "$[\"\u000f\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0010",- "selector": "$[\"\u0010\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0011",- "selector": "$[\"\u0011\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0012",- "selector": "$[\"\u0012\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0013",- "selector": "$[\"\u0013\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0014",- "selector": "$[\"\u0014\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0015",- "selector": "$[\"\u0015\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0016",- "selector": "$[\"\u0016\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0017",- "selector": "$[\"\u0017\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0018",- "selector": "$[\"\u0018\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0019",- "selector": "$[\"\u0019\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+001A",- "selector": "$[\"\u001a\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+001B",- "selector": "$[\"\u001b\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+001C",- "selector": "$[\"\u001c\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+001D",- "selector": "$[\"\u001d\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+001E",- "selector": "$[\"\u001e\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+001F",- "selector": "$[\"\u001f\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+0020",- "selector": "$[\" \"]",- "document": {- " ": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, embedded U+007F",- "selector": "$[\"\"]",- "document": {- "": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, supplementary plane character",- "selector": "$[\"𝄞\"]",- "document": {- "𝄞": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, escaped double quote",- "selector": "$[\"\\\"\"]",- "document": {- "\"": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped reverse solidus",- "selector": "$[\"\\\\\"]",- "document": {- "\\": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped solidus",- "selector": "$[\"\\/\"]",- "document": {- "/": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped backspace",- "selector": "$[\"\\b\"]",- "document": {- "\b": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped form feed",- "selector": "$[\"\\f\"]",- "document": {- "\f": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped line feed",- "selector": "$[\"\\n\"]",- "document": {- "\n": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped carriage return",- "selector": "$[\"\\r\"]",- "document": {- "\r": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped tab",- "selector": "$[\"\\t\"]",- "document": {- "\t": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, double quotes, escaped ☺, upper case hex",- "selector": "$[\"\\u263A\"]",- "document": {- "☺": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, escaped ☺, lower case hex",- "selector": "$[\"\\u263a\"]",- "document": {- "☺": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, surrogate pair 𝄞",- "selector": "$[\"\\uD834\\uDD1E\"]",- "document": {- "𝄞": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, surrogate pair 😀",- "selector": "$[\"\\uD83D\\uDE00\"]",- "document": {- "😀": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, before high surrogates",- "selector": "$[\"\\uD7FF\\uD7FF\"]",- "document": {- "": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, after low surrogates",- "selector": "$[\"\\uE000\\uE000\"]",- "document": {- "": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, invalid escaped single quote",- "selector": "$[\"\\'\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, embedded double quote",- "selector": "$[\"\"\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, incomplete escape",- "selector": "$[\"\\\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, escape at end of line",- "selector": "$[\"\\\n\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, question mark escape",- "selector": "$[\"\\?\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, bell escape",- "selector": "$[\"\\a\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, vertical tab escape",- "selector": "$[\"\\v\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, 0 escape",- "selector": "$[\"\\0\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, x escape",- "selector": "$[\"\\x12\"]",- "invalid_selector": true- },- {- "name": "name selector, double quotes, n escape",- "selector": "$[\"\\N{LATIN CAPITAL LETTER A}\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape no hex",- "selector": "$[\"\\u\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape too few hex",- "selector": "$[\"\\u123\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape upper u",- "selector": "$[\"\\U1234\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape upper u long",- "selector": "$[\"\\U0010FFFF\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape plus",- "selector": "$[\"\\u+1234\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape brackets",- "selector": "$[\"\\u{1234}\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, unicode escape brackets long",- "selector": "$[\"\\u{10ffff}\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, single high surrogate",- "selector": "$[\"\\uD800\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, single low surrogate",- "selector": "$[\"\\uDC00\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, high high surrogate",- "selector": "$[\"\\uD800\\uD800\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, low low surrogate",- "selector": "$[\"\\uDC00\\uDC00\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, surrogate non-surrogate",- "selector": "$[\"\\uD800\\u1234\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, non-surrogate surrogate",- "selector": "$[\"\\u1234\\uDC00\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, surrogate supplementary",- "selector": "$[\"\\uD800𝄞\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, supplementary surrogate",- "selector": "$[\"𝄞\\uDC00\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, double quotes, surrogate incomplete low",- "selector": "$[\"\\uD800\\uDC0\"]",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes",- "selector": "$['a']",- "document": {- "a": "A",- "b": "B"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, absent data",- "selector": "$['c']",- "document": {- "a": "A",- "b": "B"- },- "result": []- },- {- "name": "name selector, single quotes, array data",- "selector": "$['a']",- "document": [- "first",- "second"- ],- "result": []- },- {- "name": "name selector, single quotes, embedded U+0000",- "selector": "$['\u0000']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0001",- "selector": "$['\u0001']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0002",- "selector": "$['\u0002']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0003",- "selector": "$['\u0003']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0004",- "selector": "$['\u0004']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0005",- "selector": "$['\u0005']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0006",- "selector": "$['\u0006']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0007",- "selector": "$['\u0007']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0008",- "selector": "$['\b']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0009",- "selector": "$['\t']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+000A",- "selector": "$['\n']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+000B",- "selector": "$['\u000b']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+000C",- "selector": "$['\f']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+000D",- "selector": "$['\r']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+000E",- "selector": "$['\u000e']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+000F",- "selector": "$['\u000f']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0010",- "selector": "$['\u0010']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0011",- "selector": "$['\u0011']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0012",- "selector": "$['\u0012']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0013",- "selector": "$['\u0013']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0014",- "selector": "$['\u0014']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0015",- "selector": "$['\u0015']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0016",- "selector": "$['\u0016']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0017",- "selector": "$['\u0017']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0018",- "selector": "$['\u0018']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0019",- "selector": "$['\u0019']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+001A",- "selector": "$['\u001a']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+001B",- "selector": "$['\u001b']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+001C",- "selector": "$['\u001c']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+001D",- "selector": "$['\u001d']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+001E",- "selector": "$['\u001e']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+001F",- "selector": "$['\u001f']",- "invalid_selector": true,- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, embedded U+0020",- "selector": "$[' ']",- "document": {- " ": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, escaped single quote",- "selector": "$['\\'']",- "document": {- "'": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped reverse solidus",- "selector": "$['\\\\']",- "document": {- "\\": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped solidus",- "selector": "$['\\/']",- "document": {- "/": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, escaped backspace",- "selector": "$['\\b']",- "document": {- "\b": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped form feed",- "selector": "$['\\f']",- "document": {- "\f": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped line feed",- "selector": "$['\\n']",- "document": {- "\n": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped carriage return",- "selector": "$['\\r']",- "document": {- "\r": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped tab",- "selector": "$['\\t']",- "document": {- "\t": "A"- },- "result": [- "A"- ]- },- {- "name": "name selector, single quotes, escaped ☺, upper case hex",- "selector": "$['\\u263A']",- "document": {- "☺": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, escaped ☺, lower case hex",- "selector": "$['\\u263a']",- "document": {- "☺": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, surrogate pair 𝄞",- "selector": "$['\\uD834\\uDD1E']",- "document": {- "𝄞": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, surrogate pair 😀",- "selector": "$['\\uD83D\\uDE00']",- "document": {- "😀": "A"- },- "result": [- "A"- ],- "tags": [- "unicode"- ]- },- {- "name": "name selector, single quotes, invalid escaped double quote",- "selector": "$['\\\"']",- "invalid_selector": true- },- {- "name": "name selector, single quotes, embedded single quote",- "selector": "$[''']",- "invalid_selector": true- },- {- "name": "name selector, single quotes, incomplete escape",- "selector": "$['\\']",- "invalid_selector": true- },- {- "name": "name selector, double quotes, empty",- "selector": "$[\"\"]",- "document": {- "a": "A",- "b": "B",- "": "C"- },- "result": [- "C"- ]- },- {- "name": "name selector, single quotes, empty",- "selector": "$['']",- "document": {- "a": "A",- "b": "B",- "": "C"- },- "result": [- "C"- ]- },- {- "name": "slice selector, slice selector",- "selector": "$[1:3]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1,- 2- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, slice selector with step",- "selector": "$[1:6:2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1,- 3,- 5- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, slice selector with everything omitted, short form",- "selector": "$[:]",- "document": [- 0,- 1,- 2,- 3- ],- "result": [- 0,- 1,- 2,- 3- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, slice selector with everything omitted, long form",- "selector": "$[::]",- "document": [- 0,- 1,- 2,- 3- ],- "result": [- 0,- 1,- 2,- 3- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, slice selector with start omitted",- "selector": "$[:2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0,- 1- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, slice selector with start and end omitted",- "selector": "$[::2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0,- 2,- 4,- 6,- 8- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative step with default start and end",- "selector": "$[::-1]",- "document": [- 0,- 1,- 2,- 3- ],- "result": [- 3,- 2,- 1,- 0- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative step with default start",- "selector": "$[:0:-1]",- "document": [- 0,- 1,- 2,- 3- ],- "result": [- 3,- 2,- 1- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative step with default end",- "selector": "$[2::-1]",- "document": [- 0,- 1,- 2,- 3- ],- "result": [- 2,- 1,- 0- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, larger negative step",- "selector": "$[::-2]",- "document": [- 0,- 1,- 2,- 3- ],- "result": [- 3,- 1- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative range with default step",- "selector": "$[-1:-3]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative range with negative step",- "selector": "$[-1:-3:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9,- 8- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative range with larger negative step",- "selector": "$[-1:-6:-2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9,- 7,- 5- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, larger negative range with larger negative step",- "selector": "$[-1:-7:-2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9,- 7,- 5- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative from, positive to",- "selector": "$[-5:7]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 5,- 6- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative from",- "selector": "$[-2:]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 8,- 9- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, positive from, negative to",- "selector": "$[1:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative from, positive to, negative step",- "selector": "$[-1:1:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9,- 8,- 7,- 6,- 5,- 4,- 3,- 2- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, positive from, negative to, negative step",- "selector": "$[7:-5:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 7,- 6- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, too many colons",- "selector": "$[1:2:3:4]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, non-integer array index",- "selector": "$[1:2:a]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, zero step",- "selector": "$[1:2:0]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [],- "tags": [- "slice"- ]- },- {- "name": "slice selector, empty range",- "selector": "$[2:2]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [],- "tags": [- "slice"- ]- },- {- "name": "slice selector, slice selector with everything omitted with empty array",- "selector": "$[:]",- "document": [],- "result": [],- "tags": [- "slice"- ]- },- {- "name": "slice selector, negative step with empty array",- "selector": "$[::-1]",- "document": [],- "result": [],- "tags": [- "slice"- ]- },- {- "name": "slice selector, maximal range with positive step",- "selector": "$[0:10]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, maximal range with negative step",- "selector": "$[9:0:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9,- 8,- 7,- 6,- 5,- 4,- 3,- 2,- 1- ],- "tags": [- "slice"- ]- },- {- "name": "slice selector, excessively large to value",- "selector": "$[2:113667776004]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, excessively small from value",- "selector": "$[-113667776004:1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 0- ],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, excessively large from value with negative step",- "selector": "$[113667776004:0:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9,- 8,- 7,- 6,- 5,- 4,- 3,- 2,- 1- ],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, excessively small to value with negative step",- "selector": "$[3:-113667776004:-1]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 3,- 2,- 1,- 0- ],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, excessively large step",- "selector": "$[1:10:113667776004]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 1- ],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, excessively small step",- "selector": "$[-1:-10:-113667776004]",- "document": [- 0,- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9- ],- "result": [- 9- ],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, start, min exact",- "selector": "$[-9007199254740991::]",- "document": [],- "result": [],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, start, max exact",- "selector": "$[9007199254740991::]",- "document": [],- "result": [],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, start, min exact - 1",- "selector": "$[-9007199254740992::]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, start, max exact + 1",- "selector": "$[9007199254740992::]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, end, min exact",- "selector": "$[:-9007199254740991:]",- "document": [],- "result": [],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, end, max exact",- "selector": "$[:9007199254740991:]",- "document": [],- "result": [],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, end, min exact - 1",- "selector": "$[:-9007199254740992:]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, end, max exact + 1",- "selector": "$[:9007199254740992:]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, step, min exact",- "selector": "$[::-9007199254740991]",- "document": [],- "result": [],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, step, max exact",- "selector": "$[::9007199254740991]",- "document": [],- "result": [],- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, step, min exact - 1",- "selector": "$[::-9007199254740992]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, step, max exact + 1",- "selector": "$[::9007199254740992]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, overflowing to value",- "selector": "$[2:231584178474632390847141970017375815706539969331281128078915168015826259279872]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, underflowing from value",- "selector": "$[-231584178474632390847141970017375815706539969331281128078915168015826259279872:1]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, overflowing from value with negative step",- "selector": "$[231584178474632390847141970017375815706539969331281128078915168015826259279872:0:-1]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, underflowing to value with negative step",- "selector": "$[3:-231584178474632390847141970017375815706539969331281128078915168015826259279872:-1]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, overflowing step",- "selector": "$[1:10:231584178474632390847141970017375815706539969331281128078915168015826259279872]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, underflowing step",- "selector": "$[-1:-10:-231584178474632390847141970017375815706539969331281128078915168015826259279872]",- "invalid_selector": true,- "tags": [- "boundary",- "slice"- ]- },- {- "name": "slice selector, start, leading 0",- "selector": "$[01::]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, start, decimal",- "selector": "$[1.0::]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, start, plus",- "selector": "$[+1::]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, start, minus space",- "selector": "$[- 1::]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, start, -0",- "selector": "$[-0::]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, start, leading -0",- "selector": "$[-01::]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, end, leading 0",- "selector": "$[:01:]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, end, decimal",- "selector": "$[:1.0:]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, end, plus",- "selector": "$[:+1:]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, end, minus space",- "selector": "$[:- 1:]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, end, -0",- "selector": "$[:-0:]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, end, leading -0",- "selector": "$[:-01:]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, step, leading 0",- "selector": "$[::01]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, step, decimal",- "selector": "$[::1.0]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, step, plus",- "selector": "$[::+1]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, step, minus space",- "selector": "$[::- 1]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, step, -0",- "selector": "$[::-0]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "slice selector, step, leading -0",- "selector": "$[::-01]",- "invalid_selector": true,- "tags": [- "slice"- ]- },- {- "name": "functions, count, count function",- "selector": "$[?count(@..*)>2]",- "document": [- {- "a": [- 1,- 2,- 3- ]- },- {- "a": [- 1- ],- "d": "f"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": [- 1,- 2,- 3- ]- },- {- "a": [- 1- ],- "d": "f"- }- ],- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, single-node arg",- "selector": "$[?count(@.a)>1]",- "document": [- {- "a": [- 1,- 2,- 3- ]- },- {- "a": [- 1- ],- "d": "f"- },- {- "a": 1,- "d": "f"- }- ],- "result": [],- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, multiple-selector arg",- "selector": "$[?count(@['a','d'])>1]",- "document": [- {- "a": [- 1,- 2,- 3- ]- },- {- "a": [- 1- ],- "d": "f"- },- {- "a": 1,- "d": "f"- }- ],- "result": [- {- "a": [- 1- ],- "d": "f"- },- {- "a": 1,- "d": "f"- }- ],- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, non-query arg, number",- "selector": "$[?count(1)>2]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, non-query arg, string",- "selector": "$[?count('string')>2]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, non-query arg, true",- "selector": "$[?count(true)>2]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, non-query arg, false",- "selector": "$[?count(false)>2]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, non-query arg, null",- "selector": "$[?count(null)>2]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, result must be compared",- "selector": "$[?count(@..*)]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, no params",- "selector": "$[?count()==1]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, count, too many params",- "selector": "$[?count(@.a,@.b)==1]",- "invalid_selector": true,- "tags": [- "count",- "function"- ]- },- {- "name": "functions, length, string data",- "selector": "$[?length(@.a)>=2]",- "document": [- {- "a": "ab"- },- {- "a": "d"- }- ],- "result": [- {- "a": "ab"- }- ],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, string data, unicode",- "selector": "$[?length(@)==2]",- "document": [- "☺",- "☺☺",- "☺☺☺",- "ж",- "жж",- "жжж",- "磨",- "阿美",- "形声字"- ],- "result": [- "☺☺",- "жж",- "阿美"- ],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, array data",- "selector": "$[?length(@.a)>=2]",- "document": [- {- "a": [- 1,- 2,- 3- ]- },- {- "a": [- 1- ]- }- ],- "result": [- {- "a": [- 1,- 2,- 3- ]- }- ],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, missing data",- "selector": "$[?length(@.a)>=2]",- "document": [- {- "d": "f"- }- ],- "result": [],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, number arg",- "selector": "$[?length(1)>=2]",- "document": [- {- "d": "f"- }- ],- "result": [],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, true arg",- "selector": "$[?length(true)>=2]",- "document": [- {- "d": "f"- }- ],- "result": [],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, false arg",- "selector": "$[?length(false)>=2]",- "document": [- {- "d": "f"- }- ],- "result": [],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, null arg",- "selector": "$[?length(null)>=2]",- "document": [- {- "d": "f"- }- ],- "result": [],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, result must be compared",- "selector": "$[?length(@.a)]",- "invalid_selector": true,- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, no params",- "selector": "$[?length()==1]",- "invalid_selector": true,- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, too many params",- "selector": "$[?length(@.a,@.b)==1]",- "invalid_selector": true,- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, non-singular query arg",- "selector": "$[?length(@.*)<3]",- "invalid_selector": true,- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, arg is a function expression",- "selector": "$.values[?length(@.a)==length(value($..c))]",- "document": {- "c": "cd",- "values": [- {- "a": "ab"- },- {- "a": "d"- }- ]- },- "result": [- {- "a": "ab"- }- ],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, length, arg is special nothing",- "selector": "$[?length(value(@.a))>0]",- "document": [- {- "a": "ab"- },- {- "c": "d"- },- {- "a": null- }- ],- "result": [- {- "a": "ab"- }- ],- "tags": [- "function",- "length"- ]- },- {- "name": "functions, match, found match",- "selector": "$[?match(@.a, 'a.*')]",- "document": [- {- "a": "ab"- }- ],- "result": [- {- "a": "ab"- }- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, double quotes",- "selector": "$[?match(@.a, \"a.*\")]",- "document": [- {- "a": "ab"- }- ],- "result": [- {- "a": "ab"- }- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, regex from the document",- "selector": "$.values[?match(@, $.regex)]",- "document": {- "regex": "b.?b",- "values": [- "abc",- "bcd",- "bab",- "bba",- "bbab",- "b",- true,- [],- {}- ]- },- "result": [- "bab"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, don't select match",- "selector": "$[?!match(@.a, 'a.*')]",- "document": [- {- "a": "ab"- }- ],- "result": [],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, not a match",- "selector": "$[?match(@.a, 'a.*')]",- "document": [- {- "a": "bc"- }- ],- "result": [],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, select non-match",- "selector": "$[?!match(@.a, 'a.*')]",- "document": [- {- "a": "bc"- }- ],- "result": [- {- "a": "bc"- }- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, non-string first arg",- "selector": "$[?match(1, 'a.*')]",- "document": [- {- "a": "bc"- }- ],- "result": [],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, non-string second arg",- "selector": "$[?match(@.a, 1)]",- "document": [- {- "a": "bc"- }- ],- "result": [],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, filter, match function, unicode char class, uppercase",- "selector": "$[?match(@, '\\\\p{Lu}')]",- "document": [- "ж",- "Ж",- "1",- "жЖ",- true,- [],- {}- ],- "result": [- "Ж"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, filter, match function, unicode char class negated, uppercase",- "selector": "$[?match(@, '\\\\P{Lu}')]",- "document": [- "ж",- "Ж",- "1",- true,- [],- {}- ],- "result": [- "ж",- "1"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, filter, match function, unicode, surrogate pair",- "selector": "$[?match(@, 'a.b')]",- "document": [- "a𐄁b",- "ab",- "1",- true,- [],- {}- ],- "result": [- "a𐄁b"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, dot matcher on \\u2028",- "selector": "$[?match(@, '.')]",- "document": [- " ",- "\r",- "\n",- true,- [],- {}- ],- "result": [- " "- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, dot matcher on \\u2029",- "selector": "$[?match(@, '.')]",- "document": [- " ",- "\r",- "\n",- true,- [],- {}- ],- "result": [- " "- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, result cannot be compared",- "selector": "$[?match(@.a, 'a.*')==true]",- "invalid_selector": true,- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, too few params",- "selector": "$[?match(@.a)==1]",- "invalid_selector": true,- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, too many params",- "selector": "$[?match(@.a,@.b,@.c)==1]",- "invalid_selector": true,- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, arg is a function expression",- "selector": "$.values[?match(@.a, value($..['regex']))]",- "document": {- "regex": "a.*",- "values": [- {- "a": "ab"- },- {- "a": "ba"- }- ]- },- "result": [- {- "a": "ab"- }- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, dot in character class",- "selector": "$[?match(@, 'a[.b]c')]",- "document": [- "abc",- "a.c",- "axc"- ],- "result": [- "abc",- "a.c"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, escaped dot",- "selector": "$[?match(@, 'a\\\\.c')]",- "document": [- "abc",- "a.c",- "axc"- ],- "result": [- "a.c"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, escaped backslash before dot",- "selector": "$[?match(@, 'a\\\\\\\\.c')]",- "document": [- "abc",- "a.c",- "axc",- "a\\ c"- ],- "result": [- "a\\ c"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, escaped left square bracket",- "selector": "$[?match(@, 'a\\\\[.c')]",- "document": [- "abc",- "a.c",- "a[ c"- ],- "result": [- "a[ c"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, escaped right square bracket",- "selector": "$[?match(@, 'a[\\\\].]c')]",- "document": [- "abc",- "a.c",- "a c",- "a]c"- ],- "result": [- "a.c",- "a]c"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, explicit caret",- "selector": "$[?match(@, '^ab.*')]",- "document": [- "abc",- "axc",- "ab",- "xab"- ],- "result": [- "abc",- "ab"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, match, explicit dollar",- "selector": "$[?match(@, '.*bc$')]",- "document": [- "abc",- "axc",- "ab",- "abcx"- ],- "result": [- "abc"- ],- "tags": [- "function",- "match"- ]- },- {- "name": "functions, search, at the end",- "selector": "$[?search(@.a, 'a.*')]",- "document": [- {- "a": "the end is ab"- }- ],- "result": [- {- "a": "the end is ab"- }- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, double quotes",- "selector": "$[?search(@.a, \"a.*\")]",- "document": [- {- "a": "the end is ab"- }- ],- "result": [- {- "a": "the end is ab"- }- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, at the start",- "selector": "$[?search(@.a, 'a.*')]",- "document": [- {- "a": "ab is at the start"- }- ],- "result": [- {- "a": "ab is at the start"- }- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, in the middle",- "selector": "$[?search(@.a, 'a.*')]",- "document": [- {- "a": "contains two matches"- }- ],- "result": [- {- "a": "contains two matches"- }- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, regex from the document",- "selector": "$.values[?search(@, $.regex)]",- "document": {- "regex": "b.?b",- "values": [- "abc",- "bcd",- "bab",- "bba",- "bbab",- "b",- true,- [],- {}- ]- },- "result": [- "bab",- "bba",- "bbab"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, don't select match",- "selector": "$[?!search(@.a, 'a.*')]",- "document": [- {- "a": "contains two matches"- }- ],- "result": [],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, not a match",- "selector": "$[?search(@.a, 'a.*')]",- "document": [- {- "a": "bc"- }- ],- "result": [],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, select non-match",- "selector": "$[?!search(@.a, 'a.*')]",- "document": [- {- "a": "bc"- }- ],- "result": [- {- "a": "bc"- }- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, non-string first arg",- "selector": "$[?search(1, 'a.*')]",- "document": [- {- "a": "bc"- }- ],- "result": [],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, non-string second arg",- "selector": "$[?search(@.a, 1)]",- "document": [- {- "a": "bc"- }- ],- "result": [],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, filter, search function, unicode char class, uppercase",- "selector": "$[?search(@, '\\\\p{Lu}')]",- "document": [- "ж",- "Ж",- "1",- "жЖ",- true,- [],- {}- ],- "result": [- "Ж",- "жЖ"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, filter, search function, unicode char class negated, uppercase",- "selector": "$[?search(@, '\\\\P{Lu}')]",- "document": [- "ж",- "Ж",- "1",- true,- [],- {}- ],- "result": [- "ж",- "1"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, filter, search function, unicode, surrogate pair",- "selector": "$[?search(@, 'a.b')]",- "document": [- "a𐄁bc",- "abc",- "1",- true,- [],- {}- ],- "result": [- "a𐄁bc"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, dot matcher on \\u2028",- "selector": "$[?search(@, '.')]",- "document": [- " ",- "\r \n",- "\r",- "\n",- true,- [],- {}- ],- "result": [- " ",- "\r \n"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, dot matcher on \\u2029",- "selector": "$[?search(@, '.')]",- "document": [- " ",- "\r \n",- "\r",- "\n",- true,- [],- {}- ],- "result": [- " ",- "\r \n"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, result cannot be compared",- "selector": "$[?search(@.a, 'a.*')==true]",- "invalid_selector": true,- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, too few params",- "selector": "$[?search(@.a)]",- "invalid_selector": true,- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, too many params",- "selector": "$[?search(@.a,@.b,@.c)]",- "invalid_selector": true,- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, arg is a function expression",- "selector": "$.values[?search(@, value($..['regex']))]",- "document": {- "regex": "b.?b",- "values": [- "abc",- "bcd",- "bab",- "bba",- "bbab",- "b",- true,- [],- {}- ]- },- "result": [- "bab",- "bba",- "bbab"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, dot in character class",- "selector": "$[?search(@, 'a[.b]c')]",- "document": [- "x abc y",- "x a.c y",- "x axc y"- ],- "result": [- "x abc y",- "x a.c y"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, escaped dot",- "selector": "$[?search(@, 'a\\\\.c')]",- "document": [- "x abc y",- "x a.c y",- "x axc y"- ],- "result": [- "x a.c y"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, escaped backslash before dot",- "selector": "$[?search(@, 'a\\\\\\\\.c')]",- "document": [- "x abc y",- "x a.c y",- "x axc y",- "x a\\ c y"- ],- "result": [- "x a\\ c y"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, escaped left square bracket",- "selector": "$[?search(@, 'a\\\\[.c')]",- "document": [- "x abc y",- "x a.c y",- "x a[ c y"- ],- "result": [- "x a[ c y"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, search, escaped right square bracket",- "selector": "$[?search(@, 'a[\\\\].]c')]",- "document": [- "x abc y",- "x a.c y",- "x a c y",- "x a]c y"- ],- "result": [- "x a.c y",- "x a]c y"- ],- "tags": [- "function",- "search"- ]- },- {- "name": "functions, value, single-value nodelist",- "selector": "$[?value(@.*)==4]",- "document": [- [- 4- ],- {- "foo": 4- },- [- 5- ],- {- "foo": 5- },- 4- ],- "result": [- [- 4- ],- {- "foo": 4- }- ],- "tags": [- "function",- "value"- ]- },- {- "name": "functions, value, multi-value nodelist",- "selector": "$[?value(@.*)==4]",- "document": [- [- 4,- 4- ],- {- "foo": 4,- "bar": 4- }- ],- "result": [],- "tags": [- "function",- "value"- ]- },- {- "name": "functions, value, too few params",- "selector": "$[?value()==4]",- "invalid_selector": true,- "tags": [- "function",- "value"- ]- },- {- "name": "functions, value, too many params",- "selector": "$[?value(@.a,@.b)==4]",- "invalid_selector": true,- "tags": [- "function",- "value"- ]- },- {- "name": "functions, value, result must be compared",- "selector": "$[?value(@.a)]",- "invalid_selector": true,- "tags": [- "function",- "value"- ]- },- {- "name": "whitespace, filter, space between question mark and expression",- "selector": "$[? @.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, newline between question mark and expression",- "selector": "$[?\n@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, tab between question mark and expression",- "selector": "$[?\t@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, return between question mark and expression",- "selector": "$[?\r@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, space between question mark and parenthesized expression",- "selector": "$[? (@.a)]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, newline between question mark and parenthesized expression",- "selector": "$[?\n(@.a)]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, tab between question mark and parenthesized expression",- "selector": "$[?\t(@.a)]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, return between question mark and parenthesized expression",- "selector": "$[?\r(@.a)]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, space between parenthesized expression and bracket",- "selector": "$[?(@.a) ]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, newline between parenthesized expression and bracket",- "selector": "$[?(@.a)\n]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, tab between parenthesized expression and bracket",- "selector": "$[?(@.a)\t]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, return between parenthesized expression and bracket",- "selector": "$[?(@.a)\r]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, space between bracket and question mark",- "selector": "$[ ?@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, newline between bracket and question mark",- "selector": "$[\n?@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, tab between bracket and question mark",- "selector": "$[\t?@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, filter, return between bracket and question mark",- "selector": "$[\r?@.a]",- "document": [- {- "a": "b",- "d": "e"- },- {- "b": "c",- "d": "f"- }- ],- "result": [- {- "a": "b",- "d": "e"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, functions, space between function name and parenthesis",- "selector": "$[?count (@.*)==1]",- "invalid_selector": true,- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, newline between function name and parenthesis",- "selector": "$[?count\n(@.*)==1]",- "invalid_selector": true,- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, tab between function name and parenthesis",- "selector": "$[?count\t(@.*)==1]",- "invalid_selector": true,- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, return between function name and parenthesis",- "selector": "$[?count\r(@.*)==1]",- "invalid_selector": true,- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, space between parenthesis and arg",- "selector": "$[?count( @.*)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, newline between parenthesis and arg",- "selector": "$[?count(\n@.*)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, tab between parenthesis and arg",- "selector": "$[?count(\t@.*)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, return between parenthesis and arg",- "selector": "$[?count(\r@.*)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, space between arg and comma",- "selector": "$[?search(@ ,'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, newline between arg and comma",- "selector": "$[?search(@\n,'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, tab between arg and comma",- "selector": "$[?search(@\t,'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, return between arg and comma",- "selector": "$[?search(@\r,'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, space between comma and arg",- "selector": "$[?search(@, '[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, newline between comma and arg",- "selector": "$[?search(@,\n'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, tab between comma and arg",- "selector": "$[?search(@,\t'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, return between comma and arg",- "selector": "$[?search(@,\r'[a-z]+')]",- "document": [- "foo",- "123"- ],- "result": [- "foo"- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, space between arg and parenthesis",- "selector": "$[?count(@.* )==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "function",- "search",- "whitespace"- ]- },- {- "name": "whitespace, functions, newline between arg and parenthesis",- "selector": "$[?count(@.*\n)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, tab between arg and parenthesis",- "selector": "$[?count(@.*\t)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, return between arg and parenthesis",- "selector": "$[?count(@.*\r)==1]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "count",- "function",- "whitespace"- ]- },- {- "name": "whitespace, functions, spaces in a relative singular selector",- "selector": "$[?length(@ .a .b) == 3]",- "document": [- {- "a": {- "b": "foo"- }- },- {}- ],- "result": [- {- "a": {- "b": "foo"- }- }- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, newlines in a relative singular selector",- "selector": "$[?length(@\n.a\n.b) == 3]",- "document": [- {- "a": {- "b": "foo"- }- },- {}- ],- "result": [- {- "a": {- "b": "foo"- }- }- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, tabs in a relative singular selector",- "selector": "$[?length(@\t.a\t.b) == 3]",- "document": [- {- "a": {- "b": "foo"- }- },- {}- ],- "result": [- {- "a": {- "b": "foo"- }- }- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, returns in a relative singular selector",- "selector": "$[?length(@\r.a\r.b) == 3]",- "document": [- {- "a": {- "b": "foo"- }- },- {}- ],- "result": [- {- "a": {- "b": "foo"- }- }- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, spaces in an absolute singular selector",- "selector": "$..[?length(@)==length($ [0] .a)]",- "document": [- {- "a": "foo"- },- {}- ],- "result": [- "foo"- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, newlines in an absolute singular selector",- "selector": "$..[?length(@)==length($\n[0]\n.a)]",- "document": [- {- "a": "foo"- },- {}- ],- "result": [- "foo"- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, tabs in an absolute singular selector",- "selector": "$..[?length(@)==length($\t[0]\t.a)]",- "document": [- {- "a": "foo"- },- {}- ],- "result": [- "foo"- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, functions, returns in an absolute singular selector",- "selector": "$..[?length(@)==length($\r[0]\r.a)]",- "document": [- {- "a": "foo"- },- {}- ],- "result": [- "foo"- ],- "tags": [- "function",- "length",- "whitespace"- ]- },- {- "name": "whitespace, operators, space before ||",- "selector": "$[?@.a ||@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before ||",- "selector": "$[?@.a\n||@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before ||",- "selector": "$[?@.a\t||@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before ||",- "selector": "$[?@.a\r||@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after ||",- "selector": "$[?@.a|| @.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after ||",- "selector": "$[?@.a||\n@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after ||",- "selector": "$[?@.a||\t@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after ||",- "selector": "$[?@.a||\r@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "c": 3- }- ],- "result": [- {- "a": 1- },- {- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before &&",- "selector": "$[?@.a &&@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before &&",- "selector": "$[?@.a\n&&@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before &&",- "selector": "$[?@.a\t&&@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before &&",- "selector": "$[?@.a\r&&@.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after &&",- "selector": "$[?@.a&& @.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after &&",- "selector": "$[?@.a&& @.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after &&",- "selector": "$[?@.a&& @.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after &&",- "selector": "$[?@.a&& @.b]",- "document": [- {- "a": 1- },- {- "b": 2- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before ==",- "selector": "$[?@.a ==@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before ==",- "selector": "$[?@.a\n==@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before ==",- "selector": "$[?@.a\t==@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before ==",- "selector": "$[?@.a\r==@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after ==",- "selector": "$[?@.a== @.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after ==",- "selector": "$[?@.a==\n@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after ==",- "selector": "$[?@.a==\t@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after ==",- "selector": "$[?@.a==\r@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 1- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before !=",- "selector": "$[?@.a !=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before !=",- "selector": "$[?@.a\n!=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before !=",- "selector": "$[?@.a\t!=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before !=",- "selector": "$[?@.a\r!=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after !=",- "selector": "$[?@.a!= @.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after !=",- "selector": "$[?@.a!=\n@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after !=",- "selector": "$[?@.a!=\t@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after !=",- "selector": "$[?@.a!=\r@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before <",- "selector": "$[?@.a <@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before <",- "selector": "$[?@.a\n<@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before <",- "selector": "$[?@.a\t<@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before <",- "selector": "$[?@.a\r<@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after <",- "selector": "$[?@.a< @.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after <",- "selector": "$[?@.a<\n@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after <",- "selector": "$[?@.a<\t@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after <",- "selector": "$[?@.a<\r@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before >",- "selector": "$[?@.b >@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before >",- "selector": "$[?@.b\n>@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before >",- "selector": "$[?@.b\t>@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before >",- "selector": "$[?@.b\r>@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after >",- "selector": "$[?@.b> @.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after >",- "selector": "$[?@.b>\n@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after >",- "selector": "$[?@.b>\t@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after >",- "selector": "$[?@.b>\r@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "result": [- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before <=",- "selector": "$[?@.a <=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before <=",- "selector": "$[?@.a\n<=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before <=",- "selector": "$[?@.a\t<=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before <=",- "selector": "$[?@.a\r<=@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after <=",- "selector": "$[?@.a<= @.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after <=",- "selector": "$[?@.a<=\n@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after <=",- "selector": "$[?@.a<=\t@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after <=",- "selector": "$[?@.a<=\r@.b]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space before >=",- "selector": "$[?@.b >=@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline before >=",- "selector": "$[?@.b\n>=@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab before >=",- "selector": "$[?@.b\t>=@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return before >=",- "selector": "$[?@.b\r>=@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space after >=",- "selector": "$[?@.b>= @.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline after >=",- "selector": "$[?@.b>=\n@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab after >=",- "selector": "$[?@.b>=\t@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return after >=",- "selector": "$[?@.b>=\r@.a]",- "document": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- },- {- "a": 2,- "b": 1- }- ],- "result": [- {- "a": 1,- "b": 1- },- {- "a": 1,- "b": 2- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space between logical not and test expression",- "selector": "$[?! @.a]",- "document": [- {- "a": "a",- "d": "e"- },- {- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline between logical not and test expression",- "selector": "$[?!\n@.a]",- "document": [- {- "a": "a",- "d": "e"- },- {- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab between logical not and test expression",- "selector": "$[?!\t@.a]",- "document": [- {- "a": "a",- "d": "e"- },- {- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return between logical not and test expression",- "selector": "$[?!\r@.a]",- "document": [- {- "a": "a",- "d": "e"- },- {- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, space between logical not and parenthesized expression",- "selector": "$[?! (@.a=='b')]",- "document": [- {- "a": "a",- "d": "e"- },- {- "a": "b",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "a",- "d": "e"- },- {- "a": "d",- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, newline between logical not and parenthesized expression",- "selector": "$[?!\n(@.a=='b')]",- "document": [- {- "a": "a",- "d": "e"- },- {- "a": "b",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "a",- "d": "e"- },- {- "a": "d",- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, tab between logical not and parenthesized expression",- "selector": "$[?!\t(@.a=='b')]",- "document": [- {- "a": "a",- "d": "e"- },- {- "a": "b",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "a",- "d": "e"- },- {- "a": "d",- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, operators, return between logical not and parenthesized expression",- "selector": "$[?!\r(@.a=='b')]",- "document": [- {- "a": "a",- "d": "e"- },- {- "a": "b",- "d": "f"- },- {- "a": "d",- "d": "f"- }- ],- "result": [- {- "a": "a",- "d": "e"- },- {- "a": "d",- "d": "f"- }- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between root and bracket",- "selector": "$ ['a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between root and bracket",- "selector": "$\n['a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between root and bracket",- "selector": "$\t['a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between root and bracket",- "selector": "$\r['a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between bracket and bracket",- "selector": "$['a'] ['b']",- "document": {- "a": {- "b": "ab"- }- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between bracket and bracket",- "selector": "$['a'] \n['b']",- "document": {- "a": {- "b": "ab"- }- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between bracket and bracket",- "selector": "$['a'] \t['b']",- "document": {- "a": {- "b": "ab"- }- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between bracket and bracket",- "selector": "$['a'] \r['b']",- "document": {- "a": {- "b": "ab"- }- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between root and dot",- "selector": "$ .a",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between root and dot",- "selector": "$\n.a",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between root and dot",- "selector": "$\t.a",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between root and dot",- "selector": "$\r.a",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between dot and name",- "selector": "$. a",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between dot and name",- "selector": "$.\na",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between dot and name",- "selector": "$.\ta",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between dot and name",- "selector": "$.\ra",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between recursive descent and name",- "selector": "$.. a",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between recursive descent and name",- "selector": "$..\na",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between recursive descent and name",- "selector": "$..\ta",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between recursive descent and name",- "selector": "$..\ra",- "invalid_selector": true,- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between bracket and selector",- "selector": "$[ 'a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between bracket and selector",- "selector": "$[\n'a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between bracket and selector",- "selector": "$[\t'a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between bracket and selector",- "selector": "$[\r'a']",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between selector and bracket",- "selector": "$['a' ]",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between selector and bracket",- "selector": "$['a'\n]",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between selector and bracket",- "selector": "$['a'\t]",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between selector and bracket",- "selector": "$['a'\r]",- "document": {- "a": "ab"- },- "result": [- "ab"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between selector and comma",- "selector": "$['a' ,'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between selector and comma",- "selector": "$['a'\n,'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between selector and comma",- "selector": "$['a'\t,'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between selector and comma",- "selector": "$['a'\r,'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, space between comma and selector",- "selector": "$['a', 'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, newline between comma and selector",- "selector": "$['a',\n'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, tab between comma and selector",- "selector": "$['a',\t'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, selectors, return between comma and selector",- "selector": "$['a',\r'b']",- "document": {- "a": "ab",- "b": "bc"- },- "result": [- "ab",- "bc"- ],- "tags": [- "whitespace"- ]- },- {- "name": "whitespace, slice, space between start and colon",- "selector": "$[1 :5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, newline between start and colon",- "selector": "$[1\n:5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, tab between start and colon",- "selector": "$[1\t:5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, return between start and colon",- "selector": "$[1\r:5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, space between colon and end",- "selector": "$[1: 5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, newline between colon and end",- "selector": "$[1:\n5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, tab between colon and end",- "selector": "$[1:\t5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, return between colon and end",- "selector": "$[1:\r5:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, space between end and colon",- "selector": "$[1:5 :2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, newline between end and colon",- "selector": "$[1:5\n:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, tab between end and colon",- "selector": "$[1:5\t:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, return between end and colon",- "selector": "$[1:5\r:2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, space between colon and step",- "selector": "$[1:5: 2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, newline between colon and step",- "selector": "$[1:5:\n2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, tab between colon and step",- "selector": "$[1:5:\t2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- },- {- "name": "whitespace, slice, return between colon and step",- "selector": "$[1:5:\r2]",- "document": [- 1,- 2,- 3,- 4,- 5,- 6- ],- "result": [- 2,- 4- ],- "tags": [- "index",- "whitespace"- ]- }- ]-}
+ test/spec/LocatedSpec.hs view
@@ -0,0 +1,144 @@+module LocatedSpec+ ( spec )+ where++import qualified Data.Aeson as JSON+import qualified Data.Vector as V++import Data.Aeson.JSONPath (queryLocatedQQ, jsonPath)+import Data.Aeson.QQ.Simple (aesonQQ)+import Data.Aeson (Value)+import Data.Vector (Vector)+import Test.Hspec++import Prelude++getVector :: Value -> Vector Value+getVector (JSON.Array arr) = arr+getVector _ = V.empty++-- taken from https://serdejsonpath.live/+rootDoc :: Value+rootDoc = [aesonQQ|{+ "store": {+ "books": [+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]+ }+ }|]+++storeDoc :: Value+storeDoc = [aesonQQ|+ {+ "books": [+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]+ }|]++booksDoc :: Value+booksDoc = [aesonQQ| [+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]|]+++books0Doc :: Value+books0Doc = [aesonQQ|[+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ }+ ]|]+++spec :: Spec+spec = do+ describe "test queryLocated" $ do+ it "returns root document when query is $" $+ queryLocatedQQ [jsonPath|$|] rootDoc `shouldBe` V.singleton ("$",rootDoc)++ it "returns store object when queryQQ is $.store" $+ queryLocatedQQ [jsonPath|$.store|] rootDoc `shouldBe` V.fromList [("$['store']",storeDoc)]++ it "returns store object when queryQQ is $['store']" $+ queryLocatedQQ [jsonPath|$['store']|] rootDoc `shouldBe` V.fromList [("$['store']",storeDoc)]++ it "returns books array when queryQQ is $.store.books" $+ queryLocatedQQ [jsonPath|$.store.books|] rootDoc `shouldBe` V.fromList [("$['store']['books']",booksDoc)]++ it "returns 0-index book item, $.store.books[0]" $+ queryLocatedQQ [jsonPath|$.store.books[0]|] rootDoc `shouldBe` V.zip (V.singleton "$['store']['books'][0]") (getVector books0Doc)++ it "returns 0-index book item, $.store.books[-4]" $+ queryLocatedQQ [jsonPath|$.store.books[-4]|] rootDoc `shouldBe` V.zip (V.singleton "$['store']['books'][0]") (getVector books0Doc)
+ test/spec/Main.hs view
@@ -0,0 +1,29 @@+module Main+ ( main )+ where++import qualified Test.Hspec as HS++import qualified ParserSpec+import qualified QuerySpec+import qualified LocatedSpec++import Test.Hspec.Runner+import Prelude++specs :: Spec+specs = do+ HS.describe "Run all tests" $ do+ ParserSpec.spec+ QuerySpec.spec+ LocatedSpec.spec+++main :: IO ()+main = do+ summary <- hspecWithResult defaultConfig + { configColorMode = ColorAuto+ } specs+ + putStrLn $ "Total tests: " ++ show (summaryExamples summary)+ putStrLn $ "Failures: " ++ show (summaryFailures summary)
+ test/spec/ParserSpec.hs view
@@ -0,0 +1,443 @@+module ParserSpec+ ( spec )+ where++import qualified Text.ParserCombinators.Parsec as P++import Data.Aeson.JSONPath.Parser (pQuery)+import Data.Either (isLeft)++import Data.Aeson.JSONPath.Types+import Test.Hspec++import Prelude++spec :: Spec+spec = do+ describe "Parse query string" $ do+ it "parses query: $" $+ P.parse pQuery "" "$"+ `shouldBe`+ Right (Query{queryType=Root,querySegments=[]})++ it "parses query: $.store" $+ P.parse pQuery "" "$.store"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }]+ }++ it "parses query: $['store']" $+ P.parse pQuery "" "$['store']"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [Name "store"]+ }]+ }++ it "parses query: $.store.books" $+ P.parse pQuery "" "$.store.books"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }]+ }++ it "parses query: $.store.books[0]" $+ P.parse pQuery "" "$.store.books[0]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Index 0]+ }]+ }++ it "parses query: $.store.books[0,2]" $+ P.parse pQuery "" "$.store.books[0,2]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Index 0, Index 2]+ }]+ }++ it "parses query: $.store.books[1:3]" $+ P.parse pQuery "" "$.store.books[1:3]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [ArraySlice (Just 1, Just 3, 1)]+ }]+ }++ it "parses query: $.store.books[1:4:2]" $+ P.parse pQuery "" "$.store.books[1:4:2]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [ArraySlice (Just 1, Just 4, 2)]+ }]+ }++ it "parses query: $.store.books[-1:-4:-2]" $+ P.parse pQuery "" "$.store.books[-1:-4:-2]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [ArraySlice (Just (-1), Just (-4), (-2))]+ }]+ }++ it "parses query: $.store.books[1:3, 0, 1]" $+ P.parse pQuery "" "$.store.books[1:3, 0, 1]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [ArraySlice (Just 1, Just 3, 1), Index 0, Index 1]+ }]+ }++ it "parses query: $.*" $+ P.parse pQuery "" "$.*" + `shouldBe` + Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = WildcardSegment+ }]+ }++ it "parses query: $[*]" $+ P.parse pQuery "" "$[*]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [WildcardSelector]+ }]+ }++ it "parses query: $..*" $+ P.parse pQuery "" "$..*"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Descendant,+ segment = WildcardSegment+ }]+ }++ it "parses query: $..[*]" $+ P.parse pQuery "" "$..[*]"+ `shouldBe` + Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Descendant,+ segment = Bracketed [WildcardSelector]+ }]+ }++ it "fails with $.1startsWithNum" $+ P.parse pQuery "" "$.1startsWithNum"+ `shouldSatisfy` isLeft++ it "parses query $.©®±×÷Ωπ•€→∀∃∈≠≤≥✓λ" $+ P.parse pQuery "" "$.©®±×÷Ωπ•€→∀∃∈≠≤≥✓λ"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "©®±×÷Ωπ•€→∀∃∈≠≤≥✓λ"+ }]+ }++ it "parses query: $._" $+ P.parse pQuery "" "$._"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "_"+ }]+ }++ it "parses query: $.underscore_key" $+ P.parse pQuery "" "$.underscore_key"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "underscore_key"+ }]+ }++ it "parses query: $[0,TAB/LINEFEED/RETURN/SPACE1]" $+ P.parse pQuery "" "$[0,\n\t\r 1]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [Index 0, Index 1]+ }]+ }++ describe "parses JSPFilter Query" $ do+ it "$[?@.category == 'reference']" $+ P.parse pQuery "" "$[?@.category == 'reference']"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "category"]+ }) Equal (CompLit (LitString "reference")))]])]+ }]+ }++ it "test expr: $..books[?@.price].title" $+ P.parse pQuery "" "$..books[?@.price].title"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Descendant,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Test (FilterQuery Query {+ queryType = Current,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "price"+ }]+ })]])]+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "title"+ }]+ }++ it "and expr: $[?@.price < 20 && @.price > 10]" $+ P.parse pQuery "" "$[?@.price < 20 && @.price > 10]" + `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Less (CompLit (LitNum 20.0))), Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Greater (CompLit (LitNum 10.0)))]])]+ }]+ }++ it "or expr: $[?@.price < 20 || @.price > 10]" $+ P.parse pQuery "" "$[?@.price < 20 || @.price > 10]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Less (CompLit (LitNum 20.0)))], LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Greater (CompLit (LitNum 10.0)))]])]+ }]+ }++ it "root filter: $..books[?$.price].title" $+ P.parse pQuery "" "$..books[?$.price].title"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Descendant,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Test (FilterQuery Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "price"+ }]+ })]])]+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "title"+ }]+ }++ it "not expr: $[?!(@.price < 20 && @.price > 10)]" $+ P.parse pQuery "" "$[?!(@.price < 20 && @.price > 10)]" + `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [NotParen (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Less (CompLit (LitNum 20.0))), Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Greater (CompLit (LitNum 10.0)))]])]])]+ }]+ }++ it "scientific: $.store.books[?@.price < -1e20]" $+ P.parse pQuery "" "$.store.books[?@['price'] < -1e20]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Less (CompLit (LitNum (-1.0e20))))]])]+ }]+ }++ it "double: $.store.books[?@.price < 0.01]" $+ P.parse pQuery "" "$.store.books[?@['price'] < 0.01]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "price"]+ }) Less (CompLit (LitNum (1.0e-2))))]])]+ }]+ }++ it "bool: $.store.books[?@.is_available == true]" $+ P.parse pQuery "" "$.store.books[?@.is_available == true]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "is_available"]+ }) Equal (CompLit (LitBool True)))]])]+ }]+ }++ it "null: $.store.books[?@.is_available == null]" $+ P.parse pQuery "" "$.store.books[?@.is_available == null]"+ `shouldBe`+ Right Query {+ queryType = Root,+ querySegments = [QuerySegment {+ segmentType = Child,+ segment = Dotted "store"+ }, QuerySegment {+ segmentType = Child,+ segment = Dotted "books"+ }, QuerySegment {+ segmentType = Child,+ segment = Bracketed [Filter (LogicalOr [LogicalAnd [Comparison (Comp (CompSQ SingularQuery {+ singularQueryType = CurrentSQ,+ singularQuerySegments = [NameSQSeg "is_available"]+ }) Equal (CompLit LitNull))]])]+ }]+ }
+ test/spec/QuerySpec.hs view
@@ -0,0 +1,348 @@+module QuerySpec+ ( spec )+ where++import qualified Data.Vector as V+import qualified Data.Aeson as JSON++import Data.Aeson.QQ.Simple (aesonQQ)+import Data.Aeson (Value)+import Data.Vector (Vector)+import Test.Hspec++import Data.Aeson.JSONPath (queryQQ, jsonPath)++import Prelude++getVector :: Value -> Vector Value+getVector (JSON.Array arr) = arr+getVector _ = V.empty++-- taken from https://serdejsonpath.live/+rootDoc :: Value+rootDoc = [aesonQQ|{+ "store": {+ "books": [+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]+ }+ }|]+++storeDoc :: Value+storeDoc = [aesonQQ|+ {+ "books": [+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]+ }|]++booksDoc :: Value+booksDoc = [aesonQQ| [+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]|]+++books0Doc :: Value+books0Doc = [aesonQQ|[+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ }+ ]|]++books0And2Doc :: Value+books0And2Doc = [aesonQQ|[+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ }+ ]|]++books1To3Doc :: Value+books1To3Doc = [aesonQQ|[+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ }+ ]|]++books1To3And0And1Doc :: Value+books1To3And0And1Doc = [aesonQQ|[+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Guns, Germs, and Steel",+ "author": "Jared Diamond",+ "category": "reference",+ "price": 24.99+ },+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ }+ ]|]++lessThanPrice20Books :: Value+lessThanPrice20Books = [aesonQQ| [+ {+ "title": "David Copperfield",+ "author": "Charles Dickens",+ "category": "fiction",+ "price": 12.99+ },+ {+ "title": "Moby Dick",+ "author": "Herman Melville",+ "category": "fiction",+ "price": 8.99+ },+ {+ "title": "Crime and Punishment",+ "author": "Fyodor Dostoevsky",+ "category": "fiction",+ "price": 19.99+ }+ ]|]++alphaArr :: Value+alphaArr = [aesonQQ| ["a","b","c","d","e","f","g"] |]++fgArr :: Value+fgArr = [aesonQQ| ["f","g"] |]++bdArr :: Value+bdArr = [aesonQQ| ["b","d"] |]++fdArr :: Value+fdArr = [aesonQQ| ["f","d"] |]++gfedcbaArr :: Value+gfedcbaArr = [aesonQQ| ["g","f","e","d","c","b","a"] |]++rfcExample1 :: Value+rfcExample1 = [aesonQQ| {+ "o": {"j": 1, "k": 2},+ "a": [5, 3, [{"j": 4}, {"k": 6}]]+ } |]++rfcExample1Desc :: Value+rfcExample1Desc = [aesonQQ| [+ [5, 3, [{"j": 4}, {"k": 6}]],+ {"j": 1, "k": 2},+ 5,+ 3,+ [{"j": 4}, {"k": 6}],+ {"j": 4},+ {"k": 6},+ 4,+ 6,+ 1,+ 2+ ]|]++boolsAndNulls :: Value+boolsAndNulls = [aesonQQ| [+ { "a": true },+ { "a": false },+ { "a": null }+ ]|]+++boolsAndNullsA :: Value+boolsAndNullsA = [aesonQQ| [{ "a": true }] |]++boolsAndNullsB :: Value+boolsAndNullsB = [aesonQQ| [{ "a": false }] |]++boolsAndNullsC :: Value+boolsAndNullsC = [aesonQQ| [{ "a": null }] |]++spec :: Spec+spec = do+ describe "test query" $ do+ it "returns root document when query is $" $+ queryQQ [jsonPath|$|] rootDoc `shouldBe` V.singleton rootDoc++ it "returns store object when queryQQ is $.store" $+ queryQQ [jsonPath|$.store|] rootDoc `shouldBe` V.singleton storeDoc++ it "returns store object when queryQQ is $['store']" $+ queryQQ [jsonPath|$['store']|] rootDoc `shouldBe` V.singleton storeDoc++ it "returns books array when queryQQ is $.store.books" $+ queryQQ [jsonPath|$.store.books|] rootDoc `shouldBe` V.singleton booksDoc++ it "returns 0-index book item when queryQQ is $.store.books[0]" $+ queryQQ [jsonPath|$.store.books[0]|] rootDoc `shouldBe` getVector books0Doc++ it "returns 0-index book item when queryQQ is $.store.books[-4]" $+ queryQQ [jsonPath|$.store.books[-4]|] rootDoc `shouldBe` getVector books0Doc++ it "returns 0,2-index item when queryQQ is $.store.books[0,2]" $+ queryQQ [jsonPath|$.store.books[0,2]|] rootDoc `shouldBe` getVector books0And2Doc++ it "returns 1To3-index when queryQQ is $.store.books[1:3]" $+ queryQQ [jsonPath|$.store.books[1:3]|] rootDoc `shouldBe` getVector books1To3Doc++ it "returns 1To3-index and 0,1-index when queryQQ is $.store.books[1:3,0,1]" $+ queryQQ [jsonPath|$.store.books[1:3,0,1]|] rootDoc `shouldBe` getVector books1To3And0And1Doc++ it "returns slice with queryQQ $[5:]" $+ queryQQ [jsonPath|$[5:]|] alphaArr `shouldBe` getVector fgArr++ it "returns slice with queryQQ $[1:5:2]" $+ queryQQ [jsonPath|$[1:5:2]|] alphaArr `shouldBe` getVector bdArr++ it "returns slice with queryQQ $[5:1:-2]" $+ queryQQ [jsonPath|$[5:1:-2]|] alphaArr `shouldBe` getVector fdArr++ it "returns slice with queryQQ $[::-1]" $+ queryQQ [jsonPath|$[::-1]|] alphaArr `shouldBe` getVector gfedcbaArr++ it "returns root with queryQQ $.*" $+ queryQQ [jsonPath|$.*|] rootDoc `shouldBe` V.singleton storeDoc++ it "returns root with queryQQ $[*]" $+ queryQQ [jsonPath|$[*]|] rootDoc `shouldBe` V.singleton storeDoc++ it "returns descendants with queryQQ $..*" $+ queryQQ [jsonPath|$..*|] rfcExample1 `shouldBe` getVector rfcExample1Desc++ it "returns descendants with queryQQ $..[*]" $+ queryQQ [jsonPath|$..[*]|] rfcExample1 `shouldBe` getVector rfcExample1Desc++ it "returns with filtering: number comparison" $+ queryQQ [jsonPath|$.store.books[?@.price < 20]|] rootDoc+ `shouldBe` getVector lessThanPrice20Books++ it "returns with filtering: not operator" $+ queryQQ [jsonPath|$.store.books[?!(@.price < 20)]|] rootDoc+ `shouldBe` getVector books0Doc++ it "returns with filtering: true value" $+ queryQQ [jsonPath|$[?@.a == true]|] boolsAndNulls+ `shouldBe` getVector boolsAndNullsA++ it "returns with filtering: false value" $+ queryQQ [jsonPath|$[?@.a == false]|] boolsAndNulls+ `shouldBe` getVector boolsAndNullsB++ it "returns with filtering: null value" $+ queryQQ [jsonPath|$[?@.a == null]|] boolsAndNulls+ `shouldBe` getVector boolsAndNullsC++ it "returns with filtering: string comparison" $+ queryQQ [jsonPath|$.store.books[?@.author == 'Jared Diamond']|] rootDoc+ `shouldBe` getVector books0Doc++ it "returns with filtering: test expression" $+ queryQQ [jsonPath|$.store.books[?@.author]|] rootDoc+ `shouldBe` getVector booksDoc++ it "returns with filtering with spaced out segments: test expression" $+ queryQQ [jsonPath|$ .store .books[?@ .author]|] rootDoc+ `shouldBe` getVector booksDoc++ it "returns with filtering: test expr gives empty with non-existent key" $+ queryQQ [jsonPath|$.store.books[?@.not_here]|] rootDoc+ `shouldBe` V.empty