├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package.json └── test ├── multidep.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode/ 3 | test/multidep_modules/ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | - "lts/*" 5 | services: 6 | - redis-server 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LICENSE - "MIT License" 2 | 3 | Copyright (c) 2012 Daniel L. VerWeire 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-redis-jsonify 2 | ================== 3 | 4 | [![Build Status](https://travis-ci.org/wankdanker/node-redis-jsonify.svg?branch=master)](https://travis-ci.org/wankdanker/node-redis-jsonify) 5 | 6 | Save JSON representation of objects to redis when using node_redis 7 | 8 | why 9 | ------ 10 | 11 | I basically always save JSON objects to redis. As far as I can tell there isn't 12 | a way to make @mranney's [node_redis](https://github.com/mranney/node_redis) 13 | implicitly convert objects and arrays to JSON before they are sent off to redis. 14 | So I would always to have to wrap my set and get calls with JSON.parse/stringify 15 | nonsense. 16 | 17 | how 18 | ------ 19 | 20 | This module exports a function which when passed a RedisClient instance will 21 | proxy the send_command method and convert anything that is not a Buffer to and 22 | from JSON. I considered modifying the RedisClient prototype automatically when 23 | this module is included in your project, but decided against it because you may 24 | not want this behavior on all of your redis clients. 25 | 26 | compatibility 27 | ------------- 28 | 29 | This module is compatible with most versions of node_redis from 0.6.7 to 2.8.0 30 | except 2.4.2 and 2.3.1. 31 | 32 | install 33 | --------- 34 | 35 | with npm... 36 | 37 | ```bash 38 | npm install redis-jsonify 39 | ``` 40 | 41 | or with git... 42 | 43 | ```bash 44 | git clone git://github.com/wankdanker/node-redis-jsonify.git 45 | ``` 46 | 47 | example 48 | ------------ 49 | 50 | ```javascript 51 | 52 | var redis = require('redis') 53 | , jsonify = require('redis-jsonify') 54 | , client = jsonify(redis.createClient()) 55 | ; 56 | 57 | client.set('asdf', { foo : "bar" }, function (err, result) { 58 | client.get('asdf', function (err, result) { 59 | console.log(result); 60 | // should be { foo : "bar" } and not [Object object] 61 | 62 | client.quit(function () { }); 63 | }); 64 | }); 65 | 66 | ``` 67 | 68 | extras 69 | -------- 70 | 71 | I'm not a huge redis buff yet, so there may be certain commands for which this 72 | is not a good idea. One example would be the `list` command. The value returned 73 | by the `list` command is not JSON. To disable the JSON processing for certain 74 | commands there is a command blacklist array exported by the module. It currently 75 | only contains the `list` command. If you know of other commands that should be 76 | blacklisted by default or there should be special processing, let me know and 77 | I'll add them. Pull requests welcome also. 78 | 79 | ```javascript 80 | var jsonify = require('redis-jsonify'); 81 | 82 | //add somecommand to the blacklist 83 | jsonify.blacklist.push('somecommand'); 84 | 85 | //dump the blacklist to console 86 | console.log(jsonify.blacklist); 87 | ``` 88 | 89 | license 90 | ---------- 91 | 92 | ### The MIT License (MIT) 93 | 94 | 95 | Copyright (c) 2012 Daniel L. VerWeire 96 | 97 | Permission is hereby granted, free of charge, to any person obtaining 98 | a copy of this software and associated documentation files (the 99 | "Software"), to deal in the Software without restriction, including 100 | without limitation the rights to use, copy, modify, merge, publish, 101 | distribute, sublicense, and/or sell copies of the Software, and to 102 | permit persons to whom the Software is furnished to do so, subject to 103 | the following conditions: 104 | 105 | The above copyright notice and this permission notice shall be 106 | included in all copies or substantial portions of the Software. 107 | 108 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 109 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 110 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 111 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 112 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 113 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 114 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = RedisJSONify; 2 | 3 | RedisJSONify.blacklist = ["info"]; 4 | 5 | function RedisJSONify (redis, opts) { 6 | var lastArgType; 7 | 8 | opts = opts || {}; 9 | 10 | //save a reference to the real send_command method 11 | var send_command = redis.internal_send_command || redis.send_command; 12 | 13 | //define the send_command proxy method 14 | redis.internal_send_command = redis.send_command = function (command, args, callback) { 15 | var objectMode = false; 16 | var applyArgs; 17 | 18 | //don't do json stuff on blacklisted commands or if we are not ready yet 19 | if (!this.ready || ~RedisJSONify.blacklist.indexOf(command) || (command && command.command && ~RedisJSONify.blacklist.indexOf(command.command))) { 20 | return send_command.apply(redis, arguments); 21 | } 22 | 23 | if (typeof command === 'object') { 24 | objectMode = true; 25 | 26 | callback = command.callback; 27 | args = command.args; 28 | command.callback = finish; 29 | } 30 | else if (!callback) { 31 | lastArgType = typeof args[args.length - 1]; 32 | if (lastArgType === "function" || lastArgType === "undefined") { 33 | callback = args.pop(); 34 | } 35 | } 36 | 37 | //loop through each arg converting to JSON if possible 38 | args.forEach(function (arg, ix) { 39 | //only stringify the key if that has been requested 40 | if (ix === 0 && !opts.jsonKey) { 41 | //don't do anything: args[ix] = arg; 42 | } 43 | //make sure the arg is not a buffer 44 | else if (!(arg instanceof Buffer)) { 45 | args[ix] = JSON.stringify(arg); 46 | } 47 | }); 48 | 49 | if (objectMode) { 50 | applyArgs = [command]; 51 | } 52 | else { 53 | applyArgs = [command, args, finish]; 54 | } 55 | 56 | //call the real send_command method 57 | send_command.apply(redis, applyArgs); 58 | 59 | function finish (err, result) { 60 | if (Array.isArray(result)) { 61 | //loop through each array element 62 | result.forEach(function (value, ix) { 63 | if (!value instanceof Buffer) { 64 | result[ix] = JSON.parse(value); 65 | } 66 | }); 67 | } 68 | else if (!(result instanceof Buffer) && result !== "OK") { 69 | try { 70 | result = JSON.parse(result); 71 | } 72 | catch (e) { 73 | console.error("JSON.parse failed on command '%s' with value" 74 | + " '%s'. This command may need to be black listed" 75 | , command, result); 76 | } 77 | } 78 | 79 | return callback && callback(err, result); 80 | } 81 | }; 82 | 83 | return redis; 84 | } 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Dan VerWeire ", 3 | "name": "redis-jsonify", 4 | "description": "Save JSON representation of objects to redis when using node_redis", 5 | "version": "1.2.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/wankdanker/node-redis-jsonify.git" 9 | }, 10 | "dependencies": {}, 11 | "devDependencies": { 12 | "multidep": "^2.0.2", 13 | "redis": "^2.8.0", 14 | "tape": "^4.9.0" 15 | }, 16 | "optionalDependencies": {}, 17 | "engines": { 18 | "node": "*" 19 | }, 20 | "homepage": "https://github.com/wankdanker/node-redis-jsonify", 21 | "scripts": { 22 | "test": "multidep test/multidep.json && node test/test.js" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/wankdanker/node-redis-jsonify/issues" 26 | }, 27 | "main": "index.js", 28 | "directories": { 29 | "test": "test" 30 | }, 31 | "keywords": [ 32 | "redis", 33 | "json", 34 | "automatic", 35 | "implicit" 36 | ], 37 | "license": "MIT" 38 | } 39 | -------------------------------------------------------------------------------- /test/multidep.json: -------------------------------------------------------------------------------- 1 | { 2 | "path" : "test/multidep_modules", 3 | "versions" : { 4 | "redis" : ["2.8.0", "2.7.1", "2.6.5", "2.5.3", "2.2.5", "2.1.0", "2.0.1", "1.0.0", "0.12.1", "0.11.0", "0.10.3", "0.9.2", "0.8.6", "0.7.3", "0.6.7"] 5 | } 6 | } -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var test = require("tape") 2 | , jsonify = require("../") 3 | , multidep = require('multidep')('test/multidep.json') 4 | ; 5 | 6 | multidep.forEachVersion('redis', function (version, redis){ 7 | var testPrefix = 'redis@' + version + ': '; 8 | 9 | test(testPrefix + 'client gets and sets string key', function (t) { 10 | var client = jsonify(redis.createClient()) 11 | , key = "test-key-asdf" 12 | , val = { foo : "bar1" } 13 | ; 14 | 15 | t.plan(3); 16 | 17 | client.set(key, val, function (err, data) { 18 | t.error(err, 'no error returned on set'); 19 | 20 | client.get(key, function (err, data) { 21 | t.error(err, 'no error returned on get'); 22 | t.deepEqual(val, data); 23 | 24 | client.quit(function () { 25 | t.end(); 26 | }); 27 | }); 28 | }); 29 | }); 30 | 31 | test(testPrefix + 'client gets and sets string key even if it is an object when not using jsonKey', function (t) { 32 | var client = jsonify(redis.createClient()) 33 | , key = { a : "test-key-asdf" } 34 | , val = { foo : "bar2" } 35 | ; 36 | 37 | t.plan(3); 38 | 39 | client.set(key, val, function (err, data) { 40 | t.error(err, 'no error returned on set'); 41 | 42 | client.get("[object Object]", function (err, data) { 43 | t.error(err, 'no error returned on get'); 44 | t.deepEqual(val, data); 45 | 46 | client.quit(function () { 47 | t.end(); 48 | }); 49 | }); 50 | }); 51 | }); 52 | 53 | test(testPrefix + 'client sets and gets a json key', function (t) { 54 | var client = jsonify(redis.createClient(), { jsonKey : true }) 55 | , key = { b : "test-key-asdf" } 56 | , val = { foo : "bar3" } 57 | ; 58 | 59 | t.plan(3); 60 | 61 | client.set(key, val, function (err ,data) { 62 | t.error(err, 'no error returned on set'); 63 | 64 | client.get(key, function (err, data) { 65 | t.error(err, 'no error returned on get'); 66 | t.deepEqual(val, data); 67 | 68 | client.quit(function () { 69 | t.end(); 70 | }); 71 | }); 72 | }); 73 | }); 74 | }) --------------------------------------------------------------------------------