objection.js
objection.js copied to clipboard
Added $formatJson options that are passed to children/relations
PR for https://github.com/Vincit/objection.js/issues/1374
Coverage increased (+0.002%) to 97.001% when pulling c92ff221a611d8a934af19183b964d455e2cfed9 on amit-meshbey:master into 260b284a1cbfb044991894c5a3cf3dedc8ce7267 on Vincit:master.
@koskimas any chance you can have a look at it?
It can really help my project as well.
@koskimas is this something that can be merged soon?
@oxodesign in case it helps in our project we monkey patched it by requiring this file:
// objection.patch.js
/**
* This file monkey patches the objection toJson method to pass down the options to the $formatJson.
* Can be closed when this PR is merged https://github.com/Vincit/objection.js/pull/2033
*/
"use strict";
const EMPTY_ARRAY = [];
const { isInternalProp } = require("objection/lib/utils/internalPropUtils");
const { isObject, cloneDeep, isFunction } = require("objection/lib/utils/objectUtils");
const modelToJson = require("objection/lib/model/modelToJson.js");
modelToJson.toJson = function toJson(model, optIn) {
const modelClass = model.constructor;
const opt = {
virtuals: getVirtuals(optIn),
shallow: isShallow(optIn),
omit: getOmit(optIn, modelClass),
pick: null,
omitFromJson: model.$omitFromJson() || null,
cloneObjects: modelClass.cloneObjectAttributes,
format: optIn && optIn.format
};
let json = toExternalJsonImpl(model, opt);
json = model.$formatJson(json, opt.format);
return json;
};
function getVirtuals(opt) {
if (!opt) {
return true;
} else if (Array.isArray(opt.virtuals)) {
return opt.virtuals;
} else {
return opt.virtuals !== false;
}
}
function isShallow(opt) {
return !!opt && !!opt.shallow;
}
function getOmit(opt, modelClass) {
return isShallow(opt) ? modelClass.getRelationNames() : null;
}
function toExternalJsonImpl(model, opt) {
const json = {};
const keys = Object.keys(model);
const vAttr = getVirtualAttributes(model, opt);
for (let i = 0, l = keys.length; i < l; ++i) {
const key = keys[i];
const value = model[key];
assignJsonValue(json, key, value, opt);
}
if (vAttr.length !== 0) {
assignVirtualAttributes(json, model, vAttr, opt);
}
return json;
}
function getVirtualAttributes(model, opt) {
if (Array.isArray(opt.virtuals)) {
return opt.virtuals;
} else if (opt.virtuals === true) {
return model.constructor.getVirtualAttributes();
} else {
return EMPTY_ARRAY;
}
}
function assignJsonValue(json, key, value, opt) {
const type = typeof value;
if (type !== "function" && type !== "undefined" && !isInternalProp(key) && !shouldOmit(opt, key) && shouldPick(opt, key)) {
if (isObject(value)) {
json[key] = toJsonObject(value, opt);
} else {
json[key] = value;
}
}
}
function shouldOmit(opt, key) {
return (opt.omit !== null && opt.omit.includes(key)) || (opt.omitFromJson !== null && opt.omitFromJson.includes(key));
}
function shouldPick(opt, key) {
return opt.pick === null || key in opt.pick;
}
function assignVirtualAttributes(json, model, vAttr, opt) {
for (let i = 0, l = vAttr.length; i < l; ++i) {
const key = vAttr[i];
let value = model[key];
if (isFunction(value)) {
value = value.call(model);
}
assignJsonValue(json, key, value, opt);
}
}
function toJsonObject(value, opt) {
if (Array.isArray(value)) {
return toJsonArray(value, opt);
} else if (value.$isObjectionModel) {
// No branch for $toDatabaseJson here since there is never a need
// to have nested models in database rows.
return value.$toJson(opt);
} else if (Buffer.isBuffer(value)) {
return value;
} else if (opt.cloneObjects) {
return cloneDeep(value);
} else {
return value;
}
}
function toJsonArray(value, opt) {
const ret = new Array(value.length);
for (let i = 0, l = ret.length; i < l; ++i) {
const item = value[i];
if (isObject(item)) {
ret[i] = toJsonObject(item, opt);
} else {
ret[i] = item;
}
}
return ret;
}