question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Field with type Sequelize.JSON returns string when MySQL dialect is used for a MariaDB database

See original GitHub issue

What are you doing?

When querying a model, which has a field with type sequelize.JSON, it returns JSON string instead of parsed JS object for that field.

// dbService.js
// Connecting to DB, params are coming from config file
export const databaseService = new Sequelize(database, user, password, {
  host,
  port,
  dialect: 'mysql',
  logging,
  operatorsAliases: Sequelize.Op,
  define: {
    freezeTableName: true,
    charset,
    collate,
  },
});

// models/index.js
// Creating the models
import fs from 'fs';
import path from 'path';
import sequelize from 'sequelize';
import { databaseService } from 'utils/database/dbService';

const basename = path.basename(__filename);
const db = {};

fs.readdirSync(__dirname)
  .filter((file) => {
    return !file.startsWith('.') && file !== basename && file !== 'index.js' && file.slice(-3) === '.js';
  })
  .forEach((file) => {
    const fileName = path.join(__dirname, file);
    const model = require(fileName).default(databaseService, sequelize);
    db[model.name] = model;
  });

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = databaseService;
export default db;

// models/Test.js
// Creating a Test model
export default (dbService, sequelize) => {
  const Test = dbService.define('Test', {
    id: {
      type: sequelize.UUID,
      defaultValue: sequelize.UUIDV1,
      primaryKey: true,
    },

    data: {
      type: sequelize.JSON,
    },
  });

  return Test;
};

// test.js
// Usage in test script
import './models';
import { databaseService } from './dbService';

const newTest = await db.models.Test.create({
  data: { x: 1 }
});
console.log('check 1', typeof newTest.data);  // check1 object

const test = await db.models.Test.findOne({ id: newTest.id });
console.log('check 2', typeof test.data);  // check 2 string
console.log('check 3', typeof test.get('data')); // check 3 string

To Reproduce Steps to reproduce the behavior:

  1. As you can see above, I’m connecting to my DB and creating model Test, which has two fields: id and data. The latter one is of type sequelize.JSON.
  2. Then in my test script, I create an instance of Test model, providing JS object for data field. On the next line when I print type of data, it prints correctly object.
  3. However, when I query that object using findOne (no difference how you query), the returned object’s data field is string now.

What do you expect to happen?

I expect to get a parsed JS object out of my JSON field.

What is actually happening?

I’m getting JSON string instead of object.

Environment

Dialect:

  • mysql
  • postgres
  • sqlite
  • mssql
  • any

Dialect library version: mysql2 - 1.6.4 Database version: mysql Ver 15.1 Distrib 10.3.14-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2 (The DB is run in Docker using official MariaDB image) Sequelize version: 4.41.2 Node Version: v10.15.2 OS: macOS Mojave, 10.14.3 (18D109) Tested with latest release:

  • No
  • Yes, specify that version:

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:6
  • Comments:37 (10 by maintainers)

github_iconTop GitHub Comments

12reactions
omegascorpcommented, Sep 23, 2019

Looks the issue is only partially fixed in mariadb driver.

Where you read records from MariaDB via mariadb driver, Sequelize provides JSON values as objects, but if you use include, subitem JSON fields are provided as strings.

Here is a code snippet:

const User = dbService.define(
  'User',
  {
    id: {
      type: sequelize.INTEGER,
      primaryKey: true,
    },
    data: {
      type: sequelize.JSON,
      defaultValue: '',
    },
  },
);

const Project = dbService.define(
  'Project',
  {
    id: {
      type: sequelize.INTEGER,
      primaryKey: true,
    },
    data: {
      type: sequelize.JSON,
      defaultValue: '',
    },
  },
);

Project.belongsTo(User);
User.hasMany(Project, {
  foreignKey: 'userId',
  as: 'projects',
});

(async () => {
  const users = await User.findAll({
    include: [
      {
        model: Project,
        as: 'projects',
      },
    ],
    attributes: ['id', 'data', 'projects.id', 'projects.data']
  });
  console.info(typeof users[0].data); // object
  console.info(typeof users[0].projects[0].data); // string
})();

See a working demo here: https://github.com/omegascorp/sequelize-mariadb-json-test

3reactions
misos1commented, Aug 1, 2019

@papb

  • MySQL dialect + MariaDB database - string
  • MySQL dialect + MySQL database - object
  • MariaDB dialect + MariaDB database - object
Read more comments on GitHub >

github_iconTop Results From Across the Web

Sequelize JSON data type - mysql - Stack Overflow
Create a database and a Schema: var Sequelize = require('sequelize'), JsonField = require('sequelize-json'), db, User; db = new Sequelize('database', 'username ...
Read more >
Dialect-Specific Things - Sequelize
The underlying connector library used by Sequelize for MySQL is the mysql2 npm ... dialectOptions are passed directly to the MariaDB connection constructor....
Read more >
How To Use Sequelize with Node.js and MySQL - DigitalOcean
Sequelize is a Node.js-based Object Relational Mapper that makes it easy to work with MySQL, MariaDB, SQLite, PostgreSQL databases, and more ...
Read more >
sequelize 3.9.0 vulnerabilities - Snyk
sequelize is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite and Microsoft SQL Server. Affected versions of this package are vulnerable to...
Read more >
MariaDB Error Codes
A string describing the error, in this case No database selected . ... The maximum row size for the used table type, not...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found