├── .gitignore ├── index.js ├── foobar.json ├── collaborators.md ├── package.json ├── cli.js └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // var through = require('through2') 2 | var merge = require('merge-object-streams') 3 | 4 | module.exports = function(streams) { 5 | return new merge(streams) 6 | } 7 | -------------------------------------------------------------------------------- /foobar.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "a": { 5 | "all": "lowercase" 6 | }, 7 | "b": { 8 | "ALL": "CAPS" 9 | }, 10 | "c": { 11 | "All": "Propercase" 12 | } 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /collaborators.md: -------------------------------------------------------------------------------- 1 | ## Collaborators 2 | 3 | json-merge is only possible due to the excellent work of the following collaborators: 4 | 5 | 6 | 7 |
maxogdenGitHub/maxogden
finnpGitHub/finnp
8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json-merge", 3 | "version": "1.2.0", 4 | "bin": { 5 | "json-merge": "cli.js" 6 | }, 7 | "description": "given two streams of newline delimited JSON data perform a merge/extend on each object in the stream", 8 | "keywords": [ 9 | "stream", 10 | "ldjson", 11 | "ndjson", 12 | "newline", 13 | "parsing", 14 | "cli", 15 | "command-line" 16 | ], 17 | "main": "index.js", 18 | "scripts": { 19 | "test": "npm run pipe-test && npm run parse-test", 20 | "pipe-test": "cat foobar.json | json-merge \"data.*.a\" \"data.*.b\" \"data.*.c\"", 21 | "parse-test": "json-merge foobar.json --parse=\"data.*.a\" foobar.json --parse=\"data.*.b\"" 22 | }, 23 | "author": "max ogden", 24 | "license": "BSD", 25 | "dependencies": { 26 | "JSONStream": "^0.8.4", 27 | "ldjson-stream": "^1.1.0", 28 | "merge-object-streams": "0.0.3", 29 | "request": "^2.36.0" 30 | }, 31 | "devDependencies": {}, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/maxogden/json-merge.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/maxogden/json-merge/issues" 38 | }, 39 | "homepage": "https://github.com/maxogden/json-merge" 40 | } 41 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var merge = require('./') 4 | var fs = require('fs') 5 | var request = require('request') 6 | var ldj = require('ldjson-stream') 7 | var JSONStream = require('JSONStream') 8 | 9 | run() 10 | 11 | function run() { 12 | if (!process.argv[2] || !process.argv[3]) { 13 | var usage = 'Usage: json-merge [options] [options] [...]' 14 | usage += '\n\nOptions' 15 | usage += '\n--parse=\t Parse the precedent source with ' 16 | console.error(usage) 17 | } 18 | 19 | var args = process.argv.splice(2).reduce(function (sources, current, cb) { 20 | if(current.match(/^--parse=/)) { 21 | sources.push({uri: sources.pop().uri, parse: current.substring(8)}) 22 | } else { 23 | sources.push({uri: current}) 24 | } 25 | return sources 26 | }, []) 27 | 28 | var streams = args.map(getStream); 29 | var merger = merge(streams) 30 | merger.pipe(ldj.serialize()).pipe(process.stdout) 31 | } 32 | 33 | function getStream(source) { 34 | var sourceStream 35 | var uri = source.uri 36 | 37 | if (uri.match(/^http\:\/\//)) { 38 | sourceStream = request(uri) 39 | } else if (fs.existsSync(uri)) { 40 | sourceStream = fs.createReadStream(uri) 41 | } else { 42 | return process.stdin.pipe(JSONStream.parse(uri)) 43 | } 44 | 45 | if(source.parse) { 46 | return sourceStream.pipe(JSONStream.parse(source.parse)) 47 | } else { 48 | return sourceStream.pipe(ldj.parse()) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # json-merge 2 | 3 | given multiple streams of newline delimited JSON data perform a merge/extend on each object in the stream 4 | 5 | [![NPM](https://nodei.co/npm/json-merge.png?global=true)](https://nodei.co/npm/json-merge/) 6 | ![dat](http://img.shields.io/badge/Development%20sponsored%20by-dat-green.svg?style=flat) 7 | 8 | ## usage 9 | 10 | ``` 11 | npm install json-merge -g 12 | Usage: json-merge [options] [options] [...] 13 | 14 | Options 15 | --parse= Parse the precedent source with 16 | ``` 17 | 18 | sources can be one of 3 things: 19 | 20 | - paths to newline-delimited json data files 21 | - HTTP uris that return newline-delimited json data 22 | - JSONStream selector syntax to be used to parse stdin into a stream of JS objects 23 | 24 | ## examples 25 | 26 | ### newline delimited json files 27 | 28 | e.g. given a file `a.json`: 29 | 30 | ``` 31 | {"foo": "bar"} 32 | ``` 33 | 34 | and a file `b.json`: 35 | 36 | ``` 37 | {"taco": "pizza"} 38 | ``` 39 | 40 | then running: 41 | 42 | ``` 43 | json-merge a.json b.json 44 | ``` 45 | 46 | would output: 47 | 48 | ``` 49 | {"foo": "bar", "taco": "pizza"} 50 | ``` 51 | 52 | ### JSONStream parsing 53 | 54 | you can also specify [JSONStream](http://npmjs.org/JSONStream) query syntax and `json-merge` will parse stdin 55 | 56 | e.g. if `foobar.json` is: 57 | 58 | ``` 59 | { 60 | "data": [ 61 | { 62 | "a": { 63 | "all": "lowercase" 64 | }, 65 | "b": { 66 | "ALL": "CAPS" 67 | } 68 | } 69 | ] 70 | } 71 | ``` 72 | 73 | then running: 74 | 75 | ``` 76 | cat foobar.json | json-merge "data.*.a" "data.*.b" 77 | ``` 78 | 79 | would output: 80 | 81 | ``` 82 | {"all":"lowercase","ALL":"CAPS"} 83 | ``` 84 | 85 | ### Parsing different sources 86 | 87 | A given a file `food1.json`: 88 | 89 | ``` 90 | { 91 | "salty": 92 | { 93 | "tacos": "muybien", 94 | "pretzel": "jawohl" 95 | } 96 | } 97 | 98 | ``` 99 | 100 | and a file `food2.json`: 101 | 102 | ``` 103 | { 104 | "sweet": 105 | { 106 | "waffle": "delicious", 107 | "pancake": "yummy" 108 | } 109 | } 110 | ``` 111 | 112 | then running: 113 | 114 | ``` 115 | json-merge food1.json --parse="salty" food2.json --parse="sweet" 116 | ``` 117 | 118 | would output: 119 | 120 | ``` 121 | {"tacos":"muybien","pretzel":"jawohl","waffle":"delicious","pancake":"yummy"} 122 | --------------------------------------------------------------------------------