# obj — Object Utilities > `import { merge, diff, same, exists, existsAny, existsAll, isEmpty, isObj, getType, mirror, setProperty, getProperty, extractFlattenedJSON } from 'puffy-core/obj'` > CJS: `const { obj: { merge, diff, same, exists, existsAny, existsAll, isEmpty, isObj, getType, mirror, setProperty, getProperty, extractFlattenedJSON } } = require('puffy-core')` > Also available in snake_case: `exists_any`, `exists_all`, `is_empty`, `is_obj`, `get_type`, `set_property`, `get_property`, `extract_flattened_json` --- ## merge Deep merges multiple objects. Later objects override earlier ones. ### Signature ``` merge(...objects: Object[]) → Object ``` Returns: New merged object (inputs are not mutated). ### Examples ```js merge( { name:'Nic', age:38 }, { address:{ street:'hello' } }, { friends:['Peter','Roger'], address:{ code:2000 }, age:40 } ) // { // name: 'Nic', // age: 40, ← overridden by last object // address: { street: 'hello', code: 2000 }, ← deep merged // friends: ['Peter', 'Roger'] ← arrays are replaced, not merged // } ``` GOTCHA: Arrays are treated as atomic values (replaced entirely, not merged): ```js merge({ tags:['a','b'] }, { tags:['c'] }) // { tags: ['c'] } — NOT ['a','b','c'] ``` GOTCHA: `null` can override existing values: ```js merge({ x:'hello' }, { x:null }) // { x: null } — NOT { x: 'hello' } ``` GOTCHA: Date objects are treated as atomic (not recursed into): ```js merge({ d:new Date('2020-01-01') }, { d:new Date('2025-01-01') }) // { d: Date('2025-01-01') } — replaced, not merged ``` --- ## diff Returns only the properties in `current` that differ from `original`. ### Signature ``` diff(original?: Object, current?: Object) → Object ``` ### Examples ```js diff({ a:1, b:2, c:3 }, { a:1, b:99, c:3, d:4 }) // { b: 99, d: 4 } — only changed/new properties diff({ a:1 }, { a:1 }) // {} — no differences // Deep diff for nested objects diff( { user:{ name:'Nic', age:38 } }, { user:{ name:'Nic', age:40 } } ) // { user: { age: 40 } } ``` --- ## same Deep equality comparison. Returns `true` if two values are structurally equal. ### Signature ``` same(a: any, b: any, options?: { throwError?: boolean }) → boolean ``` Parameters: - `options.throwError`: If `true`, throws with a detailed message on inequality instead of returning `false`. ### Examples ```js same({ a:1, b:2 }, { a:1, b:2 }) // true same({ a:1 }, { a:2 }) // false same([1,2,3], [1,2,3]) // true same(new Date('2020-01-01'), new Date('2020-01-01')) // true ``` GOTCHA: Arrays are compared as **unordered sets** — order does not matter: ```js same([1,2,3], [3,1,2]) // true — same elements, different order ``` GOTCHA: Array comparison is O(n^2) — it checks every element against every other element. Avoid using on large arrays. ```js // With throwError for debugging: same({ a:1 }, { a:2 }, { throwError:true }) // throws Error with detailed message about what differs ``` --- ## exists / existsAny / existsAll Check for null/undefined presence. ### Signatures ``` exists(value: any) → boolean existsAny(...values: any[]) → boolean existsAll(...values: any[]) → boolean ``` `exists` returns `true` for everything EXCEPT `null` and `undefined`: ```js exists(undefined) // false exists(null) // false exists(0) // true ← unlike typical truthiness checks! exists('') // true ← unlike typical truthiness checks! exists(false) // true ← unlike typical truthiness checks! exists({}) // true exists('hello') // true existsAny(null, undefined) // false existsAny(0, undefined) // true ← 0 exists existsAll(null, undefined) // false existsAll(0, undefined) // false existsAll(0, '') // true ← both exist ``` --- ## isEmpty Checks if an object is empty (`{}`). ### Signature ``` isEmpty(obj: any) → boolean ``` ### Examples ```js isEmpty() // true isEmpty(undefined) // true isEmpty(null) // true isEmpty({}) // true isEmpty({ hello:'world' }) // false ``` --- ## isObj Checks if a value is a plain JSON-serializable object (not an array, Date, or null). ### Signature ``` isObj(value: any) → boolean ``` ### Examples ```js isObj({}) // true isObj({ a:1 }) // true isObj([]) // false — array isObj(new Date()) // false — Date isObj(null) // false isObj('string') // false ``` --- ## getType Returns a granular type string, more specific than `typeof`. ### Signature ``` getType(value: any) → 'number'|'string'|'boolean'|'undefined'|'array'|'date'|'object'|null ``` ### Examples ```js getType(42) // 'number' getType('hello') // 'string' getType(true) // 'boolean' getType(undefined) // 'undefined' getType(null) // null getType([1,2]) // 'array' ← typeof returns 'object' getType(new Date()) // 'date' ← typeof returns 'object' getType({ a:1 }) // 'object' ``` --- ## mirror Shapes an object to match a reference object's structure. ### Signature ``` mirror(obj: Object, refObj: Object) → Object ``` ### Example ```js mirror({ a:1, b:2, c:3 }, { a:null, c:null }) // { a: 1, c: 3 } — only properties from refObj are kept, using obj's values ``` --- ## setProperty Sets a nested property on an object using dot notation. Creates intermediate objects as needed. ### Signature ``` setProperty(obj: Object, prop: string, value: any) → Object ``` Returns: The mutated object (same reference). ### Examples ```js setProperty({ name:'Nic' }, 'company.name', 'Neap Pty Ltd') // { name: 'Nic', company: { name: 'Neap Pty Ltd' } } setProperty({}, 'a.b.c', 42) // { a: { b: { c: 42 } } } ``` --- ## getProperty Gets a nested property from an object using dot notation and bracket syntax for arrays. ### Signature ``` getProperty(obj: Object|Array, prop: string) → any ``` Returns: The value at the path, or `undefined` if the path doesn't exist. ### Examples ```js getProperty({ name:'Nic' }, 'name') // 'Nic' getProperty({ friends:[{ name:'Peter' }, { name:'Bob' }] }, 'friends[1].name') // 'Bob' getProperty({ a:{ b:{ c:42 } } }, 'a.b.c') // 42 // Multi-level array access getProperty({ data:[[1,2],[3,4]] }, 'data[1][0]') // 3 // Non-existent path returns undefined (no error) getProperty({ a:1 }, 'b.c.d') // undefined ``` --- ## extractFlattenedJSON Converts an object with flat dot-notation keys into a nested object structure. ### Signature ``` extractFlattenedJSON(flatObj: Object) → Object ``` ### Example ```js extractFlattenedJSON({ 'user.firstName': 'Nicolas', 'user.age': 38, 'user.friends[0].name': 'Brendan', 'user.friends[0].age': 31, 'user.friends[1].name': 'Boris', 'user.friends[1].age': 32 }) // { // user: { // firstName: 'Nicolas', // age: 38, // friends: [ // { name: 'Brendan', age: 31 }, // { name: 'Boris', age: 32 } // ] // } // } ```