quick-jsonify
Version:
A versatile JSON utility package with features like jsonify, xmlToJson, masking, validation, flattening, transformation, and more.
259 lines (214 loc) • 7.15 kB
JavaScript
function jsonify(data, options = {}) {
const indent = options.minify ? 0 : options.indent || 2;
// Handle circular references
const cache = new Set();
let transformedData = data;
// Transform keys if specified
if (options.transformKeys) {
transformedData = transformKeys(data, options.transformKeys);
}
// Masking Sensitive Data
if (options.mask && Array.isArray(options.mask)) {
transformedData = maskSensitiveData(transformedData, options.mask);
}
const jsonString = JSON.stringify(transformedData, (key, value) => {
if (typeof value === "object" && value !== null) {
if (cache.has(value)) {
return "[Circular]";
}
cache.add(value);
}
return value;
}, indent);
let transformedString = jsonString;
// Adding Comments
if (options.comments) {
transformedString = addCommentsToJson(transformedData, options.comments, indent);
}
// Sorting Keys (if specified)
if (options.sortKeys) {
const sortedData = sortObjectKeys(transformedData);
return JSON.stringify(sortedData, null, indent);
}
// Array Formatting (Inline vs Block)
if (options.arrayFormat === "inline") {
transformedString = transformedString.replace(/\[\n\s*(.*?)\n\s*\]/g, (match) => {
return match.replace(/\n\s*/g, " ");
});
}
return transformedString;
}
function getSummary(data) {
const dataType = typeof data;
const summary = {
type: dataType,
properties: dataType === 'object' ? Object.keys(data).length : 0
};
if (Array.isArray(data)) {
summary.arrayLength = data.length;
}
return summary;
}
function validate(data, schema) {
const errors = [];
for (const key in schema) {
if (typeof data[key] !== schema[key]) {
errors.push({
key,
expectedType: schema[key],
actualType: typeof data[key]
});
}
}
return {
valid: errors.length === 0,
errors
};
}
function sortObjectKeys(data) {
if (typeof data !== 'object' || data === null) return data;
if (Array.isArray(data)) return data.map(sortObjectKeys);
return Object.keys(data).sort().reduce((acc, key) => {
acc[key] = sortObjectKeys(data[key]);
return acc;
}, {});
}
function maskSensitiveData(data, keysToMask) {
if (typeof data !== 'object' || data === null) return data;
const result = Array.isArray(data) ? [...data] : { ...data };
for (const key of keysToMask) {
if (result[key]) {
result[key] = "***";
}
}
for (const key in result) {
if (typeof result[key] === 'object') {
result[key] = maskSensitiveData(result[key], keysToMask);
}
}
return result;
}
function addCommentsToJson(data, comments, indent = 2) {
let jsonString = JSON.stringify(data, null, indent);
for (const [key, comment] of Object.entries(comments)) {
const regex = new RegExp(`("${key}":\\s*[^,\\n]+)`, 'g');
jsonString = jsonString.replace(regex, `$1 // ${comment}`);
}
return jsonString;
}
function transformKeys(data, transformType) {
if (typeof data !== 'object' || data === null) return data;
const transformFn = transformType === "camelCase" ? toCamelCase : (k) => k;
const result = Array.isArray(data) ? [] : {};
for (const key in data) {
const transformedKey = transformFn(key);
result[transformedKey] = transformKeys(data[key], transformType);
}
return result;
}
function toCamelCase(str) {
return str.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
}
// New Feature: Flatten JSON Object
function flattenObject(obj, prefix = '') {
return Object.keys(obj).reduce((acc, key) => {
const newKey = prefix ? `${prefix}.${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null) {
Object.assign(acc, flattenObject(obj[key], newKey));
} else {
acc[newKey] = obj[key];
}
return acc;
}, {});
}
// New Feature: Unflatten JSON Object
function unflattenObject(data) {
const result = {};
for (const i in data) {
const keys = i.split('.');
keys.reduce((acc, key, idx) => {
return acc[key] = acc[key] || (isNaN(Number(keys[idx + 1])) ? (keys.length - 1 === idx ? data[i] : {}) : []);
}, result);
}
return result;
}
// New Feature: Deep Clone JSON Object
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
// New Feature: Pretty Print in Console
function prettyPrint(jsonObj, indent = 2) {
const formattedJson = JSON.stringify(jsonObj, null, indent);
console.log(formattedJson);
}
// New Feature: Custom Value Transformation
function transformValues(data, transformFn) {
if (typeof data !== 'object' || data === null) return data;
const result = Array.isArray(data) ? [] : {};
for (const key in data) {
result[key] = typeof data[key] === 'object' ? transformValues(data[key], transformFn) : transformFn(data[key]);
}
return result;
}
// Merges two or more JSON objects into one.
function mergeJsonObjects(...objects) {
return objects.reduce((acc, obj) => {
return { ...acc, ...obj };
}, {});
}
// Filters the JSON object to include only the specified keys.
function filterJsonKeys(data, keysToInclude) {
if (typeof data !== 'object' || data === null) return data;
return Object.keys(data).reduce((acc, key) => {
if (keysToInclude.includes(key)) {
acc[key] = data[key];
}
return acc;
}, {});
}
// Generates a sample JSON object with specified keys and default values.
function generateSampleJson(keys, defaultValue = null) {
return keys.reduce((acc, key) => {
acc[key] = defaultValue;
return acc;
}, {});
}
// Converts a JSON object into a basic XML string.
function jsonToXml(json) {
let xml = '';
for (const key in json) {
if (json.hasOwnProperty(key)) {
xml += `<${key}>${typeof json[key] === 'object' ? jsonToXml(json[key]) : json[key]}</${key}>`;
}
}
return xml;
}
// Prevents modification of a JSON object, making it immutable.
function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === 'object' && obj[key] !== null && !Object.isFrozen(obj[key])) {
deepFreeze(obj[key]);
}
});
return obj;
}
module.exports = {
jsonify,
getSummary,
validate,
sortObjectKeys,
flattenObject,
unflattenObject,
deepClone,
prettyPrint,
transformValues,
transformKeys,
mergeJsonObjects,
filterJsonKeys,
generateSampleJson,
jsonToXml,
deepFreeze,
maskSensitiveData,
addCommentsToJson
};