UNPKG

json-fetchfy

Version:

A lightweight Node.js module to fetch, validate, and manipulate JSON data from various sources seamlessly.

106 lines (93 loc) 3.78 kB
/** * @typedef {Object} FindInObjectOptions * @property {boolean} [deep=false] - If true, performs deep comparison for object queries. * @property {boolean} [caseSensitive=true] - If false, performs case-insensitive string comparisons. * @property {boolean} [returnFullPath=false] - If true, returns the full path to the matching values. * @property {boolean} [searchArrays=true] - If true, searches inside arrays. * @property {boolean} [includeArrayIndices=true] - If true, includes array indices in paths. */ /** * Finds values in an object or nested arrays based on a query. * @param {Object} obj - The object to search. * @param {*} query - The query to match against values. * @param {(string|string[])} [path=null] - Specific path(s) to search. * @param {FindInObjectOptions} [options] - Additional options for the search. * @returns {Object} An object containing matches with their paths as keys. */ function findInObject(obj, query, path = null, options = {}) { if (typeof obj !== 'object' || obj === null) { throw new TypeError("The first argument must be a non-null object"); } const { deep = false, caseSensitive = true, returnFullPath = false, searchArrays = true, includeArrayIndices = true } = options; const results = {}; const compareValues = (a, b) => { if (!caseSensitive && typeof a === 'string' && typeof b === 'string') { return a.toLowerCase() === b.toLowerCase(); } if (deep && typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) { return JSON.stringify(a) === JSON.stringify(b); } return a === b; }; const getNestedValue = (obj, path) => { const keys = Array.isArray(path) ? path : path.split('.'); return keys.reduce((acc, key) => (acc && acc[key] !== undefined) ? acc[key] : undefined, obj); }; const searchInValue = (value, currentPath, isArrayItem = false) => { // Si es una función de búsqueda personalizada if (typeof query === "function") { if (query(value, currentPath, obj)) { results[currentPath] = value; } } // Si el valor coincide directamente con la búsqueda else if (compareValues(value, query)) { results[currentPath] = value; } // Buscar en objetos anidados y arrays if (value && typeof value === 'object') { searchObject(value, currentPath); } }; const searchObject = (currentObj, currentPath = '') => { // Si es un array if (Array.isArray(currentObj)) { if (searchArrays) { currentObj.forEach((item, index) => { const newPath = includeArrayIndices ? `${currentPath}[${index}]` : currentPath; searchInValue(item, newPath, true); }); } return; } // Si es un objeto for (const key in currentObj) { const value = currentObj[key]; const newPath = currentPath ? `${currentPath}.${key}` : key; // Si se especificó una ruta, verificar si debemos buscar en esta ruta if (path) { const pathsToSearch = Array.isArray(path) ? path : [path]; if (!pathsToSearch.some(p => newPath.startsWith(p) || p.startsWith(newPath) )) { continue; } } searchInValue(value, newPath); } }; searchObject(obj); return results; } export default findInObject;