mirror of
https://github.com/thangisme/notes.git
synced 2024-11-01 04:27:17 -04:00
179 lines
4.4 KiB
Markdown
179 lines
4.4 KiB
Markdown
|
# JSONStream
|
||
|
|
||
|
streaming JSON.parse and stringify
|
||
|
|
||
|
<img src=https://secure.travis-ci.org/dominictarr/JSONStream.png?branch=master>
|
||
|
|
||
|
## example
|
||
|
|
||
|
``` js
|
||
|
|
||
|
var request = require('request')
|
||
|
, JSONStream = require('JSONStream')
|
||
|
, es = require('event-stream')
|
||
|
|
||
|
request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
|
||
|
.pipe(JSONStream.parse('rows.*'))
|
||
|
.pipe(es.mapSync(function (data) {
|
||
|
console.error(data)
|
||
|
return data
|
||
|
}))
|
||
|
```
|
||
|
|
||
|
## JSONStream.parse(path)
|
||
|
|
||
|
parse stream of values that match a path
|
||
|
|
||
|
``` js
|
||
|
JSONStream.parse('rows.*.doc')
|
||
|
```
|
||
|
|
||
|
The `..` operator is the recursive descent operator from [JSONPath](http://goessner.net/articles/JsonPath/), which will match a child at any depth (see examples below).
|
||
|
|
||
|
If your keys have keys that include `.` or `*` etc, use an array instead.
|
||
|
`['row', true, /^doc/]`.
|
||
|
|
||
|
If you use an array, `RegExp`s, booleans, and/or functions. The `..` operator is also available in array representation, using `{recurse: true}`.
|
||
|
any object that matches the path will be emitted as 'data' (and `pipe`d down stream)
|
||
|
|
||
|
If `path` is empty or null, no 'data' events are emitted.
|
||
|
|
||
|
### Examples
|
||
|
|
||
|
query a couchdb view:
|
||
|
|
||
|
``` bash
|
||
|
curl -sS localhost:5984/tests/_all_docs&include_docs=true
|
||
|
```
|
||
|
you will get something like this:
|
||
|
|
||
|
``` js
|
||
|
{"total_rows":129,"offset":0,"rows":[
|
||
|
{ "id":"change1_0.6995461115147918"
|
||
|
, "key":"change1_0.6995461115147918"
|
||
|
, "value":{"rev":"1-e240bae28c7bb3667f02760f6398d508"}
|
||
|
, "doc":{
|
||
|
"_id": "change1_0.6995461115147918"
|
||
|
, "_rev": "1-e240bae28c7bb3667f02760f6398d508","hello":1}
|
||
|
},
|
||
|
{ "id":"change2_0.6995461115147918"
|
||
|
, "key":"change2_0.6995461115147918"
|
||
|
, "value":{"rev":"1-13677d36b98c0c075145bb8975105153"}
|
||
|
, "doc":{
|
||
|
"_id":"change2_0.6995461115147918"
|
||
|
, "_rev":"1-13677d36b98c0c075145bb8975105153"
|
||
|
, "hello":2
|
||
|
}
|
||
|
},
|
||
|
]}
|
||
|
|
||
|
```
|
||
|
|
||
|
we are probably most interested in the `rows.*.docs`
|
||
|
|
||
|
create a `Stream` that parses the documents from the feed like this:
|
||
|
|
||
|
``` js
|
||
|
var stream = JSONStream.parse(['rows', true, 'doc']) //rows, ANYTHING, doc
|
||
|
|
||
|
stream.on('data', function(data) {
|
||
|
console.log('received:', data);
|
||
|
});
|
||
|
|
||
|
stream.on('root', function(root, count) {
|
||
|
if (!count) {
|
||
|
console.log('no matches found:', root);
|
||
|
}
|
||
|
});
|
||
|
```
|
||
|
awesome!
|
||
|
|
||
|
### recursive patterns (..)
|
||
|
|
||
|
`JSONStream.parser('docs..value')`
|
||
|
(or `JSONStream.parser(['docs', {recurse: true}, 'value'])` using an array)
|
||
|
will emit every `value` object that is a child, grand-child, etc. of the
|
||
|
`docs` object. In this example, it will match exactly 5 times at various depth
|
||
|
levels, emitting 0, 1, 2, 3 and 4 as results.
|
||
|
|
||
|
```js
|
||
|
{
|
||
|
"total": 5,
|
||
|
"docs": [
|
||
|
{
|
||
|
"key": {
|
||
|
"value": 0,
|
||
|
"some": "property"
|
||
|
}
|
||
|
},
|
||
|
{"value": 1},
|
||
|
{"value": 2},
|
||
|
{"blbl": [{}, {"a":0, "b":1, "value":3}, 10]},
|
||
|
{"value": 4}
|
||
|
]
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## JSONStream.parse(pattern, map)
|
||
|
|
||
|
provide a function that can be used to map or filter
|
||
|
the json output. `map` is passed the value at that node of the pattern,
|
||
|
if `map` return non-nullish (anything but `null` or `undefined`)
|
||
|
that value will be emitted in the stream. If it returns a nullish value,
|
||
|
nothing will be emitted.
|
||
|
|
||
|
## JSONStream.stringify(open, sep, close)
|
||
|
|
||
|
Create a writable stream.
|
||
|
|
||
|
you may pass in custom `open`, `close`, and `seperator` strings.
|
||
|
But, by default, `JSONStream.stringify()` will create an array,
|
||
|
(with default options `open='[\n', sep='\n,\n', close='\n]\n'`)
|
||
|
|
||
|
If you call `JSONStream.stringify(false)`
|
||
|
the elements will only be seperated by a newline.
|
||
|
|
||
|
If you only write one item this will be valid JSON.
|
||
|
|
||
|
If you write many items,
|
||
|
you can use a `RegExp` to split it into valid chunks.
|
||
|
|
||
|
## JSONStream.stringifyObject(open, sep, close)
|
||
|
|
||
|
Very much like `JSONStream.stringify`,
|
||
|
but creates a writable stream for objects instead of arrays.
|
||
|
|
||
|
Accordingly, `open='{\n', sep='\n,\n', close='\n}\n'`.
|
||
|
|
||
|
When you `.write()` to the stream you must supply an array with `[ key, data ]`
|
||
|
as the first argument.
|
||
|
|
||
|
## unix tool
|
||
|
|
||
|
query npm to see all the modules that browserify has ever depended on.
|
||
|
|
||
|
``` bash
|
||
|
curl https://registry.npmjs.org/browserify | JSONStream 'versions.*.dependencies'
|
||
|
```
|
||
|
|
||
|
## numbers
|
||
|
|
||
|
There are occasional problems parsing and unparsing very precise numbers.
|
||
|
|
||
|
I have opened an issue here:
|
||
|
|
||
|
https://github.com/creationix/jsonparse/issues/2
|
||
|
|
||
|
+1
|
||
|
|
||
|
## Acknowlegements
|
||
|
|
||
|
this module depends on https://github.com/creationix/jsonparse
|
||
|
by Tim Caswell
|
||
|
and also thanks to Florent Jaby for teaching me about parsing with:
|
||
|
https://github.com/Floby/node-json-streams
|
||
|
|
||
|
## license
|
||
|
|
||
|
MIT / APACHE2
|