You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add safer path operators and improve documentation
The documentation now does not bring the unsafe `raw` operators first,
and explains better what are the existing operators and what to be
careful about.
This also adds a new `through` operator, that allows for streaming
handling of path matches.
/** Selects the first match in the input stream. The tokens of the first matching
61
67
* value are emitted as they are read.
62
68
*
@@ -96,6 +102,25 @@ package object jsonpath {
96
102
maxNest))
97
103
.flatMap(Stream.emits(_))
98
104
105
+
/** Selects all matching elements in the input stream, feeding them to the provided [[fs2.Pipe]] in parallel.
106
+
* Each match results in a new stream of [[fs2.data.json.Token Token]] fed to the `pipe`. All the matches are processed in parallel as soon as new tokens are available.
107
+
*
108
+
* The `maxMatch` parameter controls how many matches are to be emitted at most.
109
+
* Further matches won't be emitted if any.
110
+
*
111
+
* The `maxNest` parameter controls the maximum level of match nesting to be emitted.
112
+
* E.g., if you want to emit only the top most matches, set it to `0`.
Copy file name to clipboardexpand all lines: site/documentation/json/jsonpath.md
+63-19
Original file line number
Diff line number
Diff line change
@@ -72,25 +72,28 @@ The supported JSONPath features are:
72
72
Using the path defined above, we can filter the stream of tokens, to only emit selected tokens downstream. This can be used to drastically reduce the amount of emitted data, to only the parts that are of interest for you.
73
73
The filtering pipes are located in the `fs2.data.json.jsonpath.filter` namespace.
74
74
75
-
Since JSONPath includes a recursive descent operator, there can be nested matches for your path.
76
-
The `filter.raw` emits a stream of all matches.
77
-
Each match is represented as a nested stream of JSON tokens which must be consumed.
75
+
The main operators in the namespace are:
78
76
79
-
```scala mdoc
80
-
importfs2.data.json.jsonpath.filter
77
+
-`filter.first(path)` which is a `Pipe` returning the tokens of the first match only.
78
+
-`filter.collect(path, collector)` which uses the provided `collector` to aggregate the tokens of each match, and emits all the aggregated results.
79
+
-`filter.values[Json](path)` which builds the AST for each match for any type `Json` with a [`Builder`][json-builder] in scope.
80
+
-`filter.through(path, pipe)` which sends all matches as a stream through the provided `pipe`.
81
81
82
-
importcats.effect._
83
-
importcats.effect.unsafe.implicits.global
82
+
@:callout(info)
83
+
Since JSONPath includes a recursive descent operator, there can be nested matches for your path.
84
+
The matches are returned in the order their first matching token is encountered in the input.
85
+
This means that for nested matches, the first stream returned is the ancestor element.
The matching streams are returned in the order their matching element is encountered in the input.
90
-
This means that for nested matches, the first stream returned is the ancestor element.
89
+
Using `filter.collect`, you can build a stream that collects each match for the provided collector and emits the aggregated result. For instance, to build the list of string representations of the matches, you can run the following code.
91
90
92
91
```scala mdoc
93
92
importfs2.data.json.literals._
93
+
importfs2.data.json.jsonpath.filter
94
+
95
+
importcats.effect._
96
+
importcats.effect.unsafe.implicits.global
94
97
95
98
valrecursive=jsonpath"$$..a"
96
99
@@ -106,34 +109,75 @@ val json = json"""{
106
109
107
110
json
108
111
.lift[IO]
109
-
.through(filter.raw(recursive))
110
-
.parEvalMapUnbounded(_.compile.toList)
112
+
.through(filter.collect(recursive, List))
111
113
.compile
112
114
.toList
113
115
.unsafeRunSync()
114
116
```
115
117
116
-
This is actually a common use case, so the library offers `filter.collect` to have this behavior for any collector.
118
+
If you want to have results emitted as early as possible instead of in order, you can set the `deterministic` parameter to `false`.
Copy file name to clipboardexpand all lines: site/documentation/xml/xpath.md
+61-12
Original file line number
Diff line number
Diff line change
@@ -79,47 +79,96 @@ You can use parentheses to associate differently, for instance `!(p1 && p2) || p
79
79
Using the path defined above, we can filter the stream of events, to only emit selected tokens downstream. This can be used to drastically reduce the amount of emitted data, to only the parts that are of interest for you.
80
80
The filtering pipes are located in the `fs2.data.xml.xpath.filter` namespace.
81
81
82
-
Since XPath includes a recursive descent operator, there can be nested matches for your path.
83
-
The `filter.raw` emits a stream of all matches.
84
-
Each match is represented as a nested stream of XML events which must be consumed.
82
+
The main operators in the namespace are:
83
+
84
+
-`filter.first(xpath)` which is a `Pipe` returning the events of the first match only.
85
+
-`filter.collect(xpath, collector)` which uses the provided `collector` to aggregate the events of each match, and emits all the aggregated results.
86
+
-`filter.dom[Node](xpath)` which builds the DOM for each match for any DOM type `Node` with a [`DocumentBuilder`][dom-builder] in scope.
87
+
-`filter.through(xpath, pipe)` which sends all matches as a stream through the provided `pipe`.
88
+
89
+
@:callout(info)
90
+
Since XPath includes a recursive descent operator, there can be nested matches for your xpath.
91
+
The matches are returned in the order their opening matching element is encountered in the input by default.
92
+
This means that for nested matches, the first stream returned is the ancestor element.
93
+
@:@
94
+
95
+
Using `filter.collect`, you can build a stream that collects each match for the provided collector and emits the aggregated result. For instance, to build the list of string representations of the matches, you can run the following code.
/** Selects all matching elements in the input stream, feeding them to the provided [[fs2.Pipe]] in parallel.
94
+
* Each match results in a new stream of [[fs2.data.xml.XmlEvent XmlEvent]] fed to the `pipe`. All the matches are processed in parallel as soon as new events are available.
95
+
*
96
+
* The `maxMatch` parameter controls how many matches are to be emitted at most.
97
+
* Further matches won't be emitted if any.
98
+
*
99
+
* The `maxNest` parameter controls the maximum level of match nesting to be emitted.
100
+
* E.g., if you want to emit only the top most matches, set it to `0`.
0 commit comments