├── .gitignore ├── README.md ├── index.js ├── jase.js ├── package.json └── test ├── test-lib-del.js ├── test-lib-get.js └── test-lib-save.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.seed 2 | *.log 3 | *.csv 4 | *.dat 5 | *.out 6 | *.pid 7 | *.gz 8 | *.orig 9 | 10 | work 11 | build 12 | pids 13 | logs 14 | results 15 | coverage 16 | lib-cov 17 | html-report 18 | xunit.xml 19 | node_modules 20 | npm-debug.log 21 | 22 | .project 23 | .idea 24 | .settings 25 | .iml 26 | *.sublime-workspace 27 | *.sublime-project 28 | 29 | .DS_Store* 30 | ehthumbs.db 31 | Icon? 32 | Thumbs.db 33 | .AppleDouble 34 | .LSOverride 35 | .Spotlight-V100 36 | .Trashes -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jase 2 | ==== 3 | 4 | A simple command line utility for extracting data from and writing data to JSON-formatted data structures. 5 | 6 | ``` 7 | Usage: 8 | jase [options] 9 | 10 | Arguments: 11 | A dot (`.`) delimited key which references the value that should be returned or overwritten. 12 | Escape dot characters in key names using '\', e.g. 'config.foo\.bar'. 13 | 14 | Options: 15 | -f, --file The JSON file to read. 16 | -s, --set The new value to set for the provided key. 17 | -d, --delete Delete the provided key. 18 | -i, --indent The number of spaces to indent the newly written JSON. 19 | 20 | Example: 21 | jase ./package.json scripts.test 22 | 23 | ``` 24 | 25 | ### Basic Examples 26 | 27 | #### Retrieve a value (specifying a JSON file) 28 | ```bash 29 | $ jase scripts -f package.json 30 | { 31 | "test": "tape test/*.js" 32 | } 33 | 34 | $ jase scripts.test -f package.json 35 | "tape test/*.js" 36 | ``` 37 | 38 | #### Retrieving a value (piping JSON to stdin) 39 | ```bash 40 | $ cat ./package.json | jase scripts 41 | { 42 | "test": "tape test/*.js" 43 | } 44 | 45 | $ cat ./package.json | jase scripts.test 46 | "tape test/*.js" 47 | ``` 48 | 49 | 50 | ### Sample Uses 51 | 52 | #### Get a property 53 | ```bash 54 | $ cat package.json | jase author 55 | ``` 56 | 57 | #### Get a nested property 58 | ```bash 59 | $ cat package.json | jase scripts.test 60 | ``` 61 | 62 | #### Add a property 63 | Chain operations and do things like add nested properties. 64 | ```bash 65 | $ cat package.json | jase config -s {} | jase config.port -s 8000 66 | ``` 67 | 68 | #### Delete a property 69 | ```bash 70 | $ cat package.json | jase scripts -d 71 | ``` 72 | 73 | #### Reformat a file 74 | Convert a JSON file with 2-space indenting to 4-space 75 | ```bash 76 | $ cat package.json | jase "" -i 4 77 | ``` 78 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | function split(string, delimiter) { 5 | var i, tmp, result; 6 | 7 | i = 0; 8 | tmp = ''; 9 | result = []; 10 | 11 | while (i < string.length) { 12 | if (string[i] === '\\' && string[i + 1] === delimiter) { 13 | tmp += delimiter; 14 | i += 1; 15 | } else if (string[i] === delimiter) { 16 | result.push(tmp); 17 | tmp = ''; 18 | } else { 19 | tmp += string[i]; 20 | } 21 | i += 1; 22 | } 23 | 24 | result.push(tmp); 25 | return result; 26 | } 27 | 28 | 29 | function get(src, key) { 30 | var keys, value; 31 | 32 | keys = split(key, '.'); 33 | value = src; 34 | 35 | while (value && (key = keys.shift())) { 36 | value = value[key]; 37 | } 38 | 39 | if (!keys.length) { 40 | return value; 41 | } 42 | 43 | return undefined; 44 | } 45 | 46 | 47 | function set(src, key, value) { 48 | var keys, prop, obj; 49 | 50 | keys = split(key, '.'); 51 | prop = keys.pop(); 52 | obj = src = JSON.parse(JSON.stringify(src)); 53 | 54 | while (obj && (key = keys.shift())) { 55 | obj = obj[key]; 56 | } 57 | 58 | if (!keys.length) { 59 | obj[prop] = value; 60 | return src; 61 | } 62 | 63 | return undefined; 64 | } 65 | 66 | function del(src, key) { 67 | var keys, prop, obj; 68 | 69 | keys = split(key, '.'); 70 | prop = keys.pop(); 71 | obj = src = JSON.parse(JSON.stringify(src)); 72 | 73 | while (obj && (key = keys.shift())) { 74 | obj = obj[key]; 75 | } 76 | 77 | if (!keys.length) { 78 | delete obj[prop]; 79 | return src; 80 | } 81 | 82 | return undefined; 83 | } 84 | 85 | 86 | module.exports = { 87 | get: get, 88 | set: set, 89 | del: del 90 | }; 91 | -------------------------------------------------------------------------------- /jase.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | var fs = require('fs'); 5 | var thing = require('core-util-is'); 6 | var minimist = require('minimist'); 7 | var jase = require('./index'); 8 | 9 | 10 | function parse(obj) { 11 | try { 12 | return JSON.parse(obj); 13 | } catch (err) { 14 | return obj; 15 | } 16 | } 17 | 18 | // Sort out command line arguments 19 | var opts, argv; 20 | 21 | opts = { 22 | // Save kept for backward compat. 23 | string: ['set', 'save'], 24 | alias: { 25 | file: ['f'], 26 | set: ['s'], 27 | delete: ['d'], 28 | indent: ['i'] 29 | }, 30 | default: { 31 | indent: 2 32 | } 33 | }; 34 | 35 | argv = minimist(process.argv.slice(2), opts); 36 | if (argv._.length === 0) { 37 | console.log('Usage:'); 38 | console.log(' jase [options]'); 39 | console.log(''); 40 | console.log('Arguments:'); 41 | console.log(' A dot (`.`) delimited key which references the value that should be returned or overwritten.'); 42 | console.log(' Escape dot characters in key names using \'\\\', for example \'config.foo\\.bar\'.'); 43 | console.log(''); 44 | console.log('Options:'); 45 | console.log(' -f, --file The JSON file to read.'); 46 | console.log(' -s, --set The new value to set for the provided key.'); 47 | console.log(' -d, --delete Delete the provided key.'); 48 | console.log(' -i, --indent The number of spaces to indent the newly written JSON.'); 49 | console.log(''); 50 | console.log('Example:'); 51 | console.log(' jase ./package.json scripts.test'); 52 | console.log(''); 53 | return; 54 | } 55 | 56 | 57 | // Process file. 58 | var key, chunks, stream; 59 | 60 | key = argv._[0]; 61 | chunks = []; 62 | stream = argv.file ? fs.createReadStream(argv.file) : process.stdin; 63 | 64 | stream.on('readable', function () { 65 | var chunk; 66 | while ((chunk = this.read()) !== null) { 67 | chunks.push(chunk); 68 | } 69 | }); 70 | 71 | stream.on('end', function () { 72 | var json, result, saveValue; 73 | 74 | json = Buffer.concat(chunks).toString('utf8'); 75 | json = JSON.parse(json); 76 | 77 | // Preserve fallback to `save` for backward compat reasons. 78 | if (('save' in argv) || ('set' in argv)) { 79 | saveValue = parse(argv.save || argv.set || ''); 80 | result = jase.set(json, key, saveValue); 81 | } else if (argv.delete) { 82 | result = jase.del(json, key); 83 | } else { 84 | result = jase.get(json, key); 85 | } 86 | 87 | if (result === undefined) { 88 | process.stderr.write('Error: \'' + key + '\' not found.'); 89 | process.exit(1); 90 | return; 91 | } 92 | 93 | if (!thing.isPrimitive(result)) { 94 | result = JSON.stringify(result, null, argv.indent); 95 | } 96 | 97 | process.stdout.write(result); 98 | process.exit(0); 99 | }); 100 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jase", 3 | "version": "1.2.0", 4 | "description": "Simple CLI tool for modifying JSON data.", 5 | "main": "index.js", 6 | "bin": { 7 | "jase": "jase.js" 8 | }, 9 | "scripts": { 10 | "test": "tape test/*.js" 11 | }, 12 | "keywords": [ 13 | "json", 14 | "cli", 15 | "read", 16 | "write" 17 | ], 18 | "author": "Erik Toth ", 19 | "contributors": [ 20 | "Ján Dzurek " 21 | ], 22 | "license": "ISC", 23 | "devDependencies": { 24 | "tape": "^3.0.3" 25 | }, 26 | "dependencies": { 27 | "core-util-is": "^1.0.1", 28 | "minimist": "^1.1.0" 29 | }, 30 | "directories": { 31 | "test": "test" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/totherik/jase.git" 36 | }, 37 | "bugs": { 38 | "url": "https://github.com/totherik/jase/issues" 39 | }, 40 | "homepage": "https://github.com/totherik/jase" 41 | } 42 | -------------------------------------------------------------------------------- /test/test-lib-del.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var jase = require('../index'); 3 | 4 | 5 | test(function (t) { 6 | var obj, result; 7 | 8 | t.plan(6); 9 | 10 | obj = { 11 | a: 1, 12 | b: { 13 | c: 3 14 | } 15 | }; 16 | 17 | result = jase.del(obj, 'a'); 18 | t.notOk(result.hasOwnProperty('a')); 19 | t.ok(result.hasOwnProperty('b')); 20 | t.ok(result.b.hasOwnProperty('c')); 21 | 22 | result = jase.del(obj, 'b.c'); 23 | t.ok(result.hasOwnProperty('a')); 24 | t.ok(result.hasOwnProperty('b')); 25 | t.notOk(result.b.hasOwnProperty('c')); 26 | }); 27 | -------------------------------------------------------------------------------- /test/test-lib-get.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var jase = require('../index'); 3 | 4 | 5 | test(function (t) { 6 | var obj, result; 7 | 8 | t.plan(3); 9 | 10 | obj = { 11 | a: 1, 12 | b: { 13 | c: 3 14 | }, 15 | d: [4, 5] 16 | }; 17 | 18 | result = jase.get(obj, 'a'); 19 | t.equal(result, 1); 20 | 21 | result = jase.get(obj, 'b.c'); 22 | t.equal(result, 3); 23 | 24 | result = jase.get(obj, 'd.1'); 25 | t.equal(result, 5); 26 | }); 27 | -------------------------------------------------------------------------------- /test/test-lib-save.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var jase = require('../index'); 3 | 4 | 5 | test(function (t) { 6 | var obj, result; 7 | 8 | t.plan(8); 9 | 10 | obj = { 11 | a: 1, 12 | b: { 13 | c: 3 14 | } 15 | }; 16 | 17 | result = jase.set(obj, 'a', 2); 18 | t.ok(result.hasOwnProperty('a')); 19 | t.equal(result.a, 2); 20 | t.ok(result.hasOwnProperty('b')); 21 | t.ok(result.b.hasOwnProperty('c')); 22 | 23 | result = jase.set(obj, 'b.c', 4); 24 | t.ok(result.hasOwnProperty('a')); 25 | t.ok(result.hasOwnProperty('b')); 26 | t.ok(result.b.hasOwnProperty('c')); 27 | t.equal(result.b.c, 4); 28 | }); 29 | --------------------------------------------------------------------------------