From ba70f053e5c1e26f6eaedfcee31aa8cfe4b96988 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 21 Jul 2023 20:37:54 -0700 Subject: [PATCH] v0.6.2 (#72) --- CHANGELOG.md | 9 +- lib/src/grammar/dot_name.dart | 4 +- lib/src/grammar/json_path.dart | 3 +- lib/src/grammar/parser_ext.dart | 3 + pubspec.yaml | 2 +- test/cases/cts | 2 +- test/cases/standard/expressions_equality.json | 120 ++++++++++++++++++ test/cases/standard/whitespace.json | 52 ++++++++ test/helper.dart | 14 +- 9 files changed, 194 insertions(+), 15 deletions(-) create mode 100644 test/cases/standard/whitespace.json diff --git a/CHANGELOG.md b/CHANGELOG.md index ace9775..f4562e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.2] - 2023-07-21 +### Fixed +- Disallow comparison of non-singular queries + ## [0.6.1] - 2023-07-17 ### Fixed - Allow namespace in between selector segments @@ -11,8 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.6.0] - 2023-05-27 ### Changed - Bump SDK version to 3.0.0 -- Disallow whitespace between a function name and the parentheses -- Disallow whitespace between an expression and the brackets +- Disallow whitespace between the function name and the parentheses +- Disallow whitespace between the expression and the brackets - `search()` and `match()` now strictly follow the I-Regexp convention. Expressions not conforming to I-Regexp will yield `false` regardless of the value ## [0.5.3] - 2023-04-29 \[YANKED\] @@ -156,6 +160,7 @@ Previously, no modification would be made and no errors/exceptions thrown. ### Added - Basic design draft +[0.6.2]: https://github.com/f3ath/jessie/compare/0.6.1...0.6.2 [0.6.1]: https://github.com/f3ath/jessie/compare/0.6.0...0.6.1 [0.6.0]: https://github.com/f3ath/jessie/compare/0.5.3...0.6.0 [0.5.3]: https://github.com/f3ath/jessie/compare/0.5.2...0.5.3 diff --git a/lib/src/grammar/dot_name.dart b/lib/src/grammar/dot_name.dart index 84ae54e..22ac738 100644 --- a/lib/src/grammar/dot_name.dart +++ b/lib/src/grammar/dot_name.dart @@ -1,6 +1,4 @@ import 'package:json_path/src/grammar/strings.dart'; -import 'package:json_path/src/grammar/wildcard.dart'; import 'package:petitparser/petitparser.dart'; -final dotName = - [memberNameShorthand, wildcard].toChoiceParser().skip(before: char('.')); +final dotName = memberNameShorthand.skip(before: char('.')); diff --git a/lib/src/grammar/json_path.dart b/lib/src/grammar/json_path.dart index 1041c8f..9718ccd 100644 --- a/lib/src/grammar/json_path.dart +++ b/lib/src/grammar/json_path.dart @@ -46,7 +46,7 @@ class JsonPathGrammarDefinition extends GrammarDefinition> { _unionElement().toList().inBrackets().map(unionSelector); Parser _singularUnion() => - _singularUnionElement().toList().inBrackets().map(unionSelector); + _singularUnionElement().toSingularList().inBrackets().map(unionSelector); Parser _recursion() => [ wildcard, @@ -127,6 +127,7 @@ class JsonPathGrammarDefinition extends GrammarDefinition> { Parser _segment() => [ dotName, + wildcard.skip(before: char('.')), ref0(_union), ref0(_recursion), ].toChoiceParser().trim(); diff --git a/lib/src/grammar/parser_ext.dart b/lib/src/grammar/parser_ext.dart index 56e0716..6b358d2 100644 --- a/lib/src/grammar/parser_ext.dart +++ b/lib/src/grammar/parser_ext.dart @@ -10,6 +10,9 @@ extension ParserExt on Parser { skip(before: (separator ?? char(',')).trim()).star() ].toSequenceParser().map>((v) => v.expand((e) => e).toList()); + /// Makes a list consisting of a single element. + Parser> toSingularList() => map((v) => [v]); + /// Same in parenthesis. Parser inParens() => skip(before: char('('), after: char(')')); diff --git a/pubspec.yaml b/pubspec.yaml index 268f3c5..34cca79 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: json_path -version: 0.6.1 +version: 0.6.2 description: Implementation of JSONPath expressions like "$.store.book[2].price". Reads and writes values in parsed JSON objects. homepage: "https://github.com/f3ath/jessie" diff --git a/test/cases/cts b/test/cases/cts index 84d2917..5f0291f 160000 --- a/test/cases/cts +++ b/test/cases/cts @@ -1 +1 @@ -Subproject commit 84d29173c571e72a497462d7b2ccd915bb4d85d1 +Subproject commit 5f0291f87a489ba2cb0efdc57712ee515f77736b diff --git a/test/cases/standard/expressions_equality.json b/test/cases/standard/expressions_equality.json index c4aa460..91262ca 100644 --- a/test/cases/standard/expressions_equality.json +++ b/test/cases/standard/expressions_equality.json @@ -135,6 +135,126 @@ "selector": "$[?(@.foo != @.bar)]", "document": [{"foo": 1, "bar": 2}, {"foo": 42, "bar": 42}, {"foo": 1, "bro": 1}, {}], "result": [{"foo": 1, "bar": 2}, {"foo": 1, "bro": 1}] + }, { + "name": "relative non-singular query, index, equal", + "selector": "$[?(@[0, 0]==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, index, not equal", + "selector": "$[?(@[0, 0]!=42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, index, less-or-equal", + "selector": "$[?(@[0, 0]==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, name, equal", + "selector": "$[?(@['a', 'a']==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, name, not equal", + "selector": "$[?(@['a', 'a']!=42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, name, less-or-equal", + "selector": "$[?(@['a', 'a']==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, combined, equal", + "selector": "$[?(@[0, '0']==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, combined, not equal", + "selector": "$[?(@[0, '0']!=42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, combined, less-or-equal", + "selector": "$[?(@[0, '0']==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, wildcard, equal", + "selector": "$[?(@.*==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, wildcard, not equal", + "selector": "$[?(@.*!=42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, wildcard, less-or-equal", + "selector": "$[?(@.*==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, slice, equal", + "selector": "$[?(@[0:0]==42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, slice, not equal", + "selector": "$[?(@[0:0]!=42)]", + "invalid_selector": true + }, { + "name": "relative non-singular query, slice, less-or-equal", + "selector": "$[?(@[0:0]==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, index, equal", + "selector": "$[?($[0, 0]==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, index, not equal", + "selector": "$[?($[0, 0]!=42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, index, less-or-equal", + "selector": "$[?($[0, 0]==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, name, equal", + "selector": "$[?($['a', 'a']==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, name, not equal", + "selector": "$[?($['a', 'a']!=42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, name, less-or-equal", + "selector": "$[?($['a', 'a']==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, combined, equal", + "selector": "$[?($[0, '0']==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, combined, not equal", + "selector": "$[?($[0, '0']!=42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, combined, less-or-equal", + "selector": "$[?($[0, '0']==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, wildcard, equal", + "selector": "$[?($.*==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, wildcard, not equal", + "selector": "$[?($.*!=42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, wildcard, less-or-equal", + "selector": "$[?($.*==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, slice, equal", + "selector": "$[?($[0:0]==42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, slice, not equal", + "selector": "$[?($[0:0]!=42)]", + "invalid_selector": true + }, { + "name": "absolute non-singular query, slice, less-or-equal", + "selector": "$[?($[0:0]==42)]", + "invalid_selector": true } ] } \ No newline at end of file diff --git a/test/cases/standard/whitespace.json b/test/cases/standard/whitespace.json new file mode 100644 index 0000000..a0c4707 --- /dev/null +++ b/test/cases/standard/whitespace.json @@ -0,0 +1,52 @@ +{ + "tests": [ + { + "name": "spaces in a relative singular selector", + "selector" : "$[?length(@ .a .b) == 3]", + "document" : [ {"a": {"b": "foo"}}, {} ], + "result": [ {"a": {"b": "foo"}} ] + }, + { + "name": "newlines in a relative singular selector", + "selector" : "$[?length(@\n.a\n.b) == 3]", + "document" : [ {"a": {"b": "foo"}}, {} ], + "result": [ {"a": {"b": "foo"}} ] + }, + { + "name": "tabs in a relative singular selector", + "selector" : "$[?length(@\t.a\t.b) == 3]", + "document" : [ {"a": {"b": "foo"}}, {} ], + "result": [ {"a": {"b": "foo"}} ] + }, + { + "name": "returns in a relative singular selector", + "selector" : "$[?length(@\r.a\r.b) == 3]", + "document" : [ {"a": {"b": "foo"}}, {} ], + "result": [ {"a": {"b": "foo"}} ] + }, + { + "name": "spaces in an absolute singular selector ", + "selector" : "$..[?length(@)==length($ [0] .a)]", + "document" : [ {"a": "foo"}, {} ], + "result": [ "foo" ] + }, + { + "name": "newlines in an absolute singular selector ", + "selector" : "$..[?length(@)==length($\n[0]\n.a)]", + "document" : [ {"a": "foo"}, {} ], + "result": [ "foo" ] + }, + { + "name": "tabs in an absolute singular selector ", + "selector" : "$..[?length(@)==length($\t[0]\t.a)]", + "document" : [ {"a": "foo"}, {} ], + "result": [ "foo" ] + }, + { + "name": "returns in an absolute singular selector ", + "selector" : "$..[?length(@)==length($\r[0]\r.a)]", + "document" : [ {"a": "foo"}, {} ], + "result": [ "foo" ] + } + ] +} \ No newline at end of file diff --git a/test/helper.dart b/test/helper.dart index 0a7225f..3c27afb 100644 --- a/test/helper.dart +++ b/test/helper.dart @@ -27,13 +27,13 @@ void runTestsInDirectory(String dirName, {JsonPathParser? parser}) { } final document = t['document']; - final name = t['name'] as String?; - final paths = t['paths'] as List?; - final pointers = t['pointers'] as List?; - final selector = t['selector'] as String; - final skip = t['skip'] as String?; - final values = t['result'] as List?; - final invalid = t['invalid_selector'] as bool?; + final String? name = t['name']; + final List? paths = t['paths']; + final List? pointers = t['pointers']; + final String selector = t['selector']; + final String? skip = t['skip']; + final List? values = t['result']; + final bool? invalid = t['invalid_selector']; group(name ?? selector, () { if (values is List) { test('values', () {