From ae3cf25e773f695d3e646ace05bdd3b4d90344da Mon Sep 17 00:00:00 2001 From: Siim Sams Date: Mon, 19 Jun 2023 18:24:13 +0300 Subject: [PATCH] fix: null value not persisted for properties of type JSON, Any, or Object Signed-off-by: Siim Sams --- lib/dao.js | 8 ++++--- test/loopback-dl.test.js | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/lib/dao.js b/lib/dao.js index ada5541c1..f34ed8b32 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -179,10 +179,12 @@ DataAccessObject._forDB = function(data) { const res = {}; for (const propName in data) { const type = this.getPropertyType(propName); - if (type === 'JSON' || type === 'Any' || type === 'Object' || data[propName] instanceof Array) { - res[propName] = JSON.stringify(data[propName]); + const value = data[propName]; + if (value !== null && (type === 'JSON' || type === 'Any' || + type === 'Object' || value instanceof Array)) { + res[propName] = JSON.stringify(value); } else { - res[propName] = data[propName]; + res[propName] = value; } } return res; diff --git a/test/loopback-dl.test.js b/test/loopback-dl.test.js index a009be55a..e135224ce 100644 --- a/test/loopback-dl.test.js +++ b/test/loopback-dl.test.js @@ -1363,6 +1363,58 @@ describe('Model define with scopes configuration', function() { }); }); +describe('DataAccessObject._forDB', function() { + const ds = new DataSource('memory'); + const dao = ds.DataAccessObject; + + it('should return input data if dataSource is not relational', function() { + const inputData = {testKey: 'testValue'}; + dao.getDataSource = () => ({isRelational: () => false}); + + const outputData = dao._forDB(inputData); + + assert.deepEqual(outputData, inputData); + }); + + it('should return JSON stringified values for appropriate types', function() { + const inputData = { + key1: [1, 2, 3], + key2: {subKey: 'value'}, + key3: 'nonJSONvalue', + }; + dao.getDataSource = () => ({isRelational: () => true}); + dao.getPropertyType = (propName) => (propName !== 'key3' ? 'JSON' : 'String'); + + const outputData = dao._forDB(inputData); + + assert.deepEqual(outputData, { + key1: JSON.stringify([1, 2, 3]), + key2: JSON.stringify({subKey: 'value'}), + key3: 'nonJSONvalue', + }); + }); + + it('should return original value for non JSON, non Array types', function() { + const inputData = {key1: 'string', key2: 123, key3: true}; + dao.getDataSource = () => ({isRelational: () => true}); + dao.getPropertyType = () => 'String'; + + const outputData = dao._forDB(inputData); + + assert.deepEqual(outputData, inputData); + }); + + it('should not process null values', function() { + const inputData = {key1: 'value', key2: null}; + dao.getDataSource = () => ({isRelational: () => true}); + dao.getPropertyType = (propName) => 'JSON'; + + const outputData = dao._forDB(inputData); + + assert.deepEqual(outputData, {key1: JSON.stringify('value'), key2: null}); + }); +}); + describe('DataAccessObject', function() { let ds, model, where, error, filter;