├── .gitignore ├── package.json ├── README.md ├── index.js └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sequelize-json", 3 | "version": "2.1.2", 4 | "description": "Automatic serialization/parsing of JSON in your models", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "clear && mocha test" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/Growmies/sequelize-json.git" 15 | }, 16 | "keywords": [ 17 | "sequelize", 18 | "json" 19 | ], 20 | "author": "Scott Hillman", 21 | "license": "ISC", 22 | "bugs": { 23 | "url": "https://github.com/Growmies/sequelize-json/issues" 24 | }, 25 | "homepage": "https://github.com/Growmies/sequelize-json", 26 | "devDependencies": { 27 | "chai": "^2.0.0", 28 | "mocha": "^2.1.0", 29 | "sqlite3": "^3.0.5" 30 | }, 31 | "dependencies": { 32 | "sequelize": "^3.6.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sequelize-json 2 | 3 | #### Want to store JSON data in your database (that isn't PostGres)? This is for you. 4 | 5 | 6 | ## How 7 | 8 | 9 | * Create a database and a Schema: 10 | 11 | 12 | ```javascript 13 | 14 | var Sequelize = require('sequelize'), 15 | JsonField = require('sequelize-json'), 16 | db, 17 | User; 18 | 19 | db = new Sequelize('database', 'username', 'password', { 20 | dialect: 'sqlite', 21 | logging: false 22 | }); 23 | 24 | User = db.define('User', { 25 | username: Sequelize.STRING, 26 | jsonField: JsonField(db, 'User', 'jsonField') 27 | }); 28 | ``` 29 | 30 | _Note the parameters of JsonField, you pass your Sequelize instance, the name of the model, and the name of the field. A little awkard, but this is needed in order to add the proper hooks to the model instance._ 31 | 32 | Now, you can always treat that field as a json object: 33 | 34 | ```javascript 35 | User.create({ 36 | username: 'Scott', 37 | jsonField: { 38 | likes: ['running', 'node'] 39 | } 40 | }) 41 | .then(function(user) { 42 | user.jsonField.likes.push('tests'); 43 | return user.save(); 44 | }) 45 | .then(function(user) { 46 | expect(user.jsonField).to.be.a('object'); 47 | expect(user.jsonField.likes).to.have.length(3); 48 | }); 49 | ``` 50 | 51 | It will work with normal `save` commands, as well as `updateAttribute` commands. 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var Sequelize = require('sequelize'); 2 | 3 | function JsonField(db, modelName, fieldName, options) { 4 | var self = this; 5 | options = options || {}; 6 | 7 | process.nextTick(function() { 8 | function stringifyField(instance) { 9 | if (typeof instance.dataValues[fieldName] !== 'string' && instance.dataValues[fieldName]) { 10 | instance.setDataValue(fieldName, JSON.stringify(instance.getDataValue(fieldName))); 11 | return self; 12 | } else if (instance.dataValues[fieldName] === 'null' || !instance.dataValues[fieldName]) { 13 | instance.setDataValue(fieldName, undefined); 14 | } 15 | } 16 | if (typeof db.models === 'object' && db.models.hasOwnProperty(modelName) && typeof db.models[modelName].hook === 'function') { 17 | db.models[modelName].hook('beforeUpdate', stringifyField); 18 | db.models[modelName].hook('beforeCreate', stringifyField); 19 | } 20 | }); 21 | 22 | var model = { 23 | type: options.type || Sequelize.TEXT, 24 | get: function() { 25 | var currentValue = this.getDataValue(fieldName); 26 | if (typeof currentValue == 'string') { 27 | this.dataValues[fieldName] = JSON.parse(currentValue); 28 | } 29 | return this.dataValues[fieldName]; 30 | }, 31 | set: function(value) { 32 | this.setDataValue(fieldName, JSON.stringify(value)); 33 | } 34 | }; 35 | 36 | if (options.hasOwnProperty('defaultValue')) { 37 | model.defaultValue = JSON.stringify(options.defaultValue); 38 | } 39 | 40 | return model; 41 | } 42 | 43 | module.exports = JsonField; 44 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var Sequelize = require('sequelize'), 2 | mocha = require('mocha'), 3 | expect = require('chai').expect, 4 | JsonField = require('../'), 5 | db, 6 | User; 7 | 8 | describe('Test the various uses of the JSON field', function() { 9 | 10 | beforeEach(function(done) { 11 | db = new Sequelize('database', 'username', 'password', { 12 | dialect: 'sqlite', 13 | logging: false 14 | }); 15 | 16 | User = db.define('User', { 17 | username: Sequelize.STRING, 18 | jsonField: new JsonField(db, 'User', 'jsonField') 19 | }); 20 | 21 | db 22 | .sync({ force: true }) 23 | .then(function() { 24 | done(); 25 | }); 26 | }); 27 | 28 | it('Should test the basic use case of a JSON field', function(done) { 29 | User.create({ 30 | username: 'Scott', 31 | jsonField: { likes: ['running', 'node', 'tests'] } 32 | }) 33 | .then(function(user) { 34 | expect(user.jsonField).to.be.a('object'); 35 | expect(user.jsonField.likes).to.have.length(3); 36 | done(); 37 | }) 38 | .catch(done); 39 | 40 | }); 41 | 42 | it('Should test updating the JSON field with `updateAttributes`', function(done) { 43 | User.create({ 44 | username: 'Scott', 45 | jsonField: { 46 | likes: ['running', 'node'] 47 | } 48 | }) 49 | .then(function(user) { 50 | var jsonField = user.jsonField; 51 | jsonField.likes.push('tests'); 52 | 53 | return user.updateAttributes({ 54 | jsonField : jsonField 55 | }); 56 | }) 57 | .then(function(user) { 58 | expect(user.jsonField).to.be.a('object'); 59 | expect(user.jsonField.likes).to.have.length(3); 60 | done(); 61 | }) 62 | .catch(done); 63 | 64 | }); 65 | 66 | it('Should also work with modifying the JSON field directly and then calling `save`', function(done) { 67 | User.create({ 68 | username: 'Scott', 69 | jsonField: { 70 | likes: ['running', 'node'] 71 | } 72 | }) 73 | .then(function(user) { 74 | user.jsonField.likes.push('tests'); 75 | return user.save(); 76 | }) 77 | .then(function(user) { 78 | expect(user.jsonField).to.be.a('object'); 79 | expect(user.jsonField.likes).to.have.length(3); 80 | done(); 81 | }) 82 | .catch(done); 83 | }); 84 | 85 | it('Should work to create a user, modify the JSON field, save, then retrieve, and access the JSON field', function(done) { 86 | User.create({ 87 | username: 'Scott', 88 | jsonField: { 89 | likes: ['running', 'node'] 90 | } 91 | }) 92 | .then(function(user) { 93 | user.jsonField.likes.push('tests'); 94 | return user.save(); 95 | }) 96 | .then(function(user) { 97 | return User.findById(user.id); 98 | }) 99 | .then(function(fetchedUser) { 100 | expect(fetchedUser.jsonField).to.be.a('object'); 101 | expect(fetchedUser.jsonField.likes).to.have.length(3); 102 | done(); 103 | }) 104 | .catch(done); 105 | }); 106 | 107 | it('You should be able to modify the json field and see how it changes before you call save', function(done) { 108 | User.create({ 109 | username: 'Scott', 110 | jsonField: { 111 | likes: ['running', 'node'] 112 | } 113 | }) 114 | .then(function(user) { 115 | user.jsonField.likes.push('tests'); 116 | expect(user.jsonField).to.be.a('object'); 117 | expect(user.jsonField.likes).to.have.length(3); 118 | done(); 119 | }) 120 | .catch(done); 121 | }); 122 | 123 | it('Default value should be undefined if nothing is provided', function(done) { 124 | User.create({ 125 | username: 'Scott' 126 | }) 127 | .then(function(user) { 128 | expect(user.jsonField).to.be.a('undefined'); 129 | done(); 130 | }) 131 | .catch(done); 132 | }); 133 | }); 134 | 135 | describe('Test default values', function() { 136 | 137 | beforeEach(function(done) { 138 | db = new Sequelize('database', 'username', 'password', { 139 | dialect: 'sqlite', 140 | logging: false 141 | }); 142 | 143 | User = db.define('User', { 144 | username: Sequelize.STRING, 145 | jsonField: new JsonField(db, 'User', 'jsonField', { defaultValue: { stuff: 'stuffValue' }}) 146 | }); 147 | 148 | db 149 | .sync({ force: true }) 150 | .then(function() { 151 | done(); 152 | }); 153 | }); 154 | 155 | it('Should be able to pass in a default value', function(done) { 156 | User.create({ 157 | username: 'Scott' 158 | }) 159 | .then(function(user) { 160 | expect(user.jsonField).to.be.a('object'); 161 | expect(user.jsonField.stuff).to.equal('stuffValue'); 162 | done(); 163 | }) 164 | .catch(done); 165 | }); 166 | 167 | it('You should be able to override the default value', function(done) { 168 | User.create({ 169 | username: 'Scott', 170 | jsonField: { 171 | likes: ['running', 'node'] 172 | } 173 | }) 174 | .then(function(user) { 175 | user.jsonField.likes.push('tests'); 176 | expect(user.jsonField).to.be.a('object'); 177 | expect(user.jsonField.likes).to.have.length(3); 178 | done(); 179 | }) 180 | .catch(done); 181 | }); 182 | 183 | 184 | }); 185 | --------------------------------------------------------------------------------