modelToJson.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. const { mergeQueryProps } = require('./modelQueryProps');
  2. const { isObject, cloneDeep } = require('../utils/objectUtils');
  3. function toJson(model, opt) {
  4. const modelClass = model.constructor;
  5. if (!isObject(opt)) {
  6. opt = {};
  7. }
  8. // We don't take a copy of `opt` here which can cause some problems in some
  9. // super rare cases since we modify an object passed from the outside. I can't
  10. // think of a realistic scenario where this would actually have some unwanted
  11. // effects. We don't take a copy for performance reasons.
  12. opt.omit = null;
  13. opt.pick = null;
  14. opt.omitFromJson = model.$omitFromJson() || null;
  15. if (opt.virtuals === undefined) {
  16. opt.virtuals = true;
  17. }
  18. if (opt.shallow) {
  19. opt.omit = modelClass.getRelations();
  20. }
  21. let json = toExternalJsonImpl(model, opt);
  22. return model.$formatJson(json);
  23. }
  24. function toDatabaseJson(model, knex) {
  25. const modelClass = model.constructor;
  26. const jsonSchema = modelClass.getJsonSchema();
  27. const opt = {
  28. virtuals: false,
  29. shallow: true,
  30. omit: modelClass.getRelations(),
  31. pick: (jsonSchema && modelClass.pickJsonSchemaProperties && jsonSchema.properties) || null,
  32. omitFromJson: model.$omitFromDatabaseJson() || null
  33. };
  34. let json = toDatabaseJsonImpl(model, opt);
  35. json = model.$formatDatabaseJson(json);
  36. return mergeQueryProps(model, json, knex);
  37. }
  38. function toExternalJsonImpl(model, opt) {
  39. const json = {};
  40. const keys = Object.keys(model);
  41. const vAttr = model.constructor.virtualAttributes;
  42. for (let i = 0, l = keys.length; i < l; ++i) {
  43. const key = keys[i];
  44. const value = model[key];
  45. assignJsonValue(json, key, value, opt);
  46. }
  47. if (vAttr && opt.virtuals === true) {
  48. assignVirtualAttributes(json, model, vAttr, opt);
  49. }
  50. return json;
  51. }
  52. function toDatabaseJsonImpl(model, opt) {
  53. const json = {};
  54. const keys = Object.keys(model);
  55. for (let i = 0, l = keys.length; i < l; ++i) {
  56. const key = keys[i];
  57. const value = model[key];
  58. assignJsonValue(json, key, value, opt);
  59. }
  60. return json;
  61. }
  62. function assignJsonValue(json, key, value, opt) {
  63. const type = typeof value;
  64. if (
  65. (opt.omit === null || !(key in opt.omit)) &&
  66. (opt.pick === null || key in opt.pick) &&
  67. (opt.omitFromJson === null || opt.omitFromJson.indexOf(key) === -1) &&
  68. type !== 'function' &&
  69. type !== 'undefined' &&
  70. key[0] !== '$'
  71. ) {
  72. if (isObject(value)) {
  73. json[key] = toJsonObject(value, opt);
  74. } else {
  75. json[key] = value;
  76. }
  77. }
  78. }
  79. function assignVirtualAttributes(json, model, vAttr, opt) {
  80. for (let i = 0, l = vAttr.length; i < l; ++i) {
  81. const key = vAttr[i];
  82. let value = model[key];
  83. if (typeof value === 'function') {
  84. value = value.call(model);
  85. }
  86. assignJsonValue(json, key, value, opt);
  87. }
  88. }
  89. function toJsonObject(value, opt) {
  90. if (Array.isArray(value)) {
  91. return toJsonArray(value, opt);
  92. } else if (value.$isObjectionModel) {
  93. // No branch for $toDatabaseJson here since there is never a need
  94. // to have nested models in database rows.
  95. return value.$toJson(opt);
  96. } else if (Buffer.isBuffer(value)) {
  97. return value;
  98. } else {
  99. return cloneDeep(value);
  100. }
  101. }
  102. function toJsonArray(value, opt) {
  103. const ret = new Array(value.length);
  104. for (let i = 0, l = ret.length; i < l; ++i) {
  105. const item = value[i];
  106. if (isObject(item)) {
  107. ret[i] = toJsonObject(item, opt);
  108. } else {
  109. ret[i] = item;
  110. }
  111. }
  112. return ret;
  113. }
  114. module.exports = {
  115. toJson,
  116. toDatabaseJson
  117. };