diff --git a/lib/parsers/text_parser.js b/lib/parsers/text_parser.js index 0af4a7ab45..49a128c049 100644 --- a/lib/parsers/text_parser.js +++ b/lib/parsers/text_parser.js @@ -85,8 +85,15 @@ function compile(fields, options, config) { db: field.schema, table: field.table, name: field.name, - string: function() { - return _this.packet.readLengthCodedString(field.encoding); + string: function(encoding = field.encoding) { + if (field.columnType === Types.JSON && encoding === field.encoding) { + // Since for JSON columns mysql always returns charset 63 (BINARY), + // we have to handle it according to JSON specs and use "utf8", + // see https://github.com/sidorares/node-mysql2/issues/1661 + console.warn(`typeCast: JSON column "${field.name}" is interpreted as BINARY by default, recommended to manually set utf8 encoding: \`field.string("utf8")\``); + } + + return _this.packet.readLengthCodedString(encoding); }, buffer: function() { return _this.packet.readLengthCodedBuffer(); @@ -172,7 +179,7 @@ function compile(fields, options, config) { } else { parserFn(`${lvalue} = ${readCode};`); } - } + } } parserFn('return result;'); @@ -191,7 +198,7 @@ function compile(fields, options, config) { } if (typeof options.typeCast === 'function') { return parserFn.toFunction({wrap}); - } + } return parserFn.toFunction(); } diff --git a/test/unit/parsers/test-text-parser.js b/test/unit/parsers/test-text-parser.js new file mode 100644 index 0000000000..01d77c1109 --- /dev/null +++ b/test/unit/parsers/test-text-parser.js @@ -0,0 +1,38 @@ +'use strict'; + +const assert = require('assert'); +const common = require('../../common'); + +const typeCastWrapper = function (...args) { + return function (field, next) { + if (field.type === 'JSON') { + return JSON.parse(field.string(...args)); + } + + return next(); + } +} + +const connection = common.createConnection(); +connection.query('CREATE TEMPORARY TABLE t (i JSON)'); +connection.query('INSERT INTO t values(\'{ "test": "😀" }\')'); + +// JSON without encoding options - should result in unexpected behaviors +connection.query({ + sql: 'SELECT * FROM t', + typeCast: typeCastWrapper() +}, (err, rows) => { + assert.ifError(err); + assert.notEqual(rows[0].i.test, "😀"); +}); + +// JSON with encoding explicitly set to utf8 +connection.query({ + sql: 'SELECT * FROM t', + typeCast: typeCastWrapper("utf8") +}, (err, rows) => { + assert.ifError(err); + assert.equal(rows[0].i.test, "😀"); +}); + +connection.end();