J'ai défini un modèle comme
module.exports = function (sequelize, DataTypes) {
const MyModel = sequelize.define('MyModel', {
data: {
type: DataTypes.JSON,
...
},
...
});
return MyModel;
};
Je l'interroge en utilisant
MyModel.findAll().then(myModels => ...);
Cependant, le champ data
dans le résultat de la requête est une chaîne, pas un objet JSON. Comment je le répare?
Ce n'est pas encore pris en charge MySQL JSON Data Type # 4727 . Mais vous pouvez faire quelque chose comme ça:
module.exports = function (sequelize, DataTypes) {
const MyModel = sequelize.define('MyModel', {
data: {
type: Sequelize.TEXT,
get: function () {
return JSON.parse(this.getDataValue('value'));
},
set: function (value) {
this.setDataValue('value', JSON.stringify(value));
},
,
...
},
...
});
return MyModel;
};
J'ai également trouvé ce paquet sur github sequelize-json vous pouvez l'essayer si vous ne voulez pas utiliser les getters et les setters.
La réponse de Jalal a été excellente, mais n'a pas fonctionné pour moi à moins que je l'aie légèrement modifiée. Voici ce qui a fonctionné pour moi:
First: créer une migration qui ajoute le champ souhaité en tant que type TEXT
. exemple - Je veux ajouter un champ appelé address
à la table Stores
:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.addColumn("Stores", "address", Sequelize.TEXT);
},
down: (queryInterface, Sequelize) => {
return queryInterface.removeColumn("Stores", "address");
}
};
Next: A l'intérieur de votre modèle, ajoutez le champ avec des getters et setters à votre liste (objet) de champs et de types de données:
address: {
type: DataTypes.TEXT,
get: function() {
return JSON.parse(this.getDataValue("address"));
},
set: function(value) {
return this.setDataValue("address", JSON.stringify(value));
}
},
Donc, mon modèle entier ressemble à ceci:
module.exports = (sequelize, DataTypes) => {
const Store = sequelize.define(
"Store",
{
name: DataTypes.STRING,
isActive: DataTypes.BOOLEAN,
address: {
type: DataTypes.TEXT,
get: function() {
return JSON.parse(this.getDataValue("address"));
},
set: function(value) {
return this.setDataValue("address", JSON.stringify(value));
}
}
},
{}
);
Store.associate = function(models) {
// associations can be defined here
Store.hasMany(models.Order, {
foreignKey: "id",
targetKey: "storeId"
});
};
return Store;
};
Maintenant vous pouvez créer et récupérer des enregistrements comme vous le feriez avec un champ de type JSON dans la base de données.
Par exemple: const store = await Store.create({name: "Joe's corner store", address: {address1: "123 test street", city: "Los Angeles", state: "CA"}})
Quelques notes:
Dans les blocs de code ci-dessus ...
address
par le nom de champ que vous souhaitez utiliser.Stores
par le nom de votre modèle/table.return
sur le setter, sinon il faisait une erreur en essayant de créer un nouvel enregistrement (comme Jalal l'a).Les types de données JSON ne sont pas pris en charge pour MySQL.
Voir les documents ici http://docs.sequelizejs.com/en/v3/docs/models-definition/#data-types
Une solution de contournement pourrait être d'utiliser du texte et de stringify/parse lors de l'interrogation
La solution la plus simple consiste à utiliser cette petite bibliothèque appelée sequelize-json
Créez une base de données et un schéma:
var Sequelize = require('sequelize'),
JsonField = require('sequelize-json'),
db,
User;
db = new Sequelize('database', 'username', 'password', {
dialect: 'sqlite',
logging: false
});
User = db.define('User', {
username: Sequelize.STRING,
jsonField: JsonField(db, 'User', 'jsonField')
});
Notez les paramètres de JsonField, vous passez votre instance Sequelize, le nom du modèle et le nom du champ. Un peu gênant, mais cela est nécessaire pour ajouter les crochets appropriés à l'instance de modèle.
Maintenant, vous pouvez toujours traiter ce champ comme un objet json:
User.create({
username: 'Scott',
jsonField: {
likes: ['running', 'node']
}
})
.then(function(user) {
user.jsonField.likes.Push('tests');
return user.save();
})
.then(function(user) {
expect(user.jsonField).to.be.a('object');
expect(user.jsonField.likes).to.have.length(3);
});
Plus besoin d'utiliser des getters et setters car JSON est maintenant supporté par sequelize.See sequelize api