jpflat
Flatten objects or arrays to an object with no nested objects where the keys are json paths by default
Inflate objects from a flattened object back to a regular nested object
Any promises that are encountered will be resolved
To prevent traversal into certain types (i.e. Dates), pass an array of valueSerializers to flatten or valueDeserializers to inflate.
Path generation can be customized to whatever scheme fits your needs.
By default, Date objects are converted to the string: DATE_${date.toISOString}
. The prefix is necessary for deserializing back to a date type.
Dots in property names will be escaped with a backslash. i.e. 127.0.0.1 => 127\.0\.0\.1
Basic Functionality
For example, an object like this:
const foo = name: 'bob' datas: some: foos: true rayray: nested: rayray: true false nestedArrays: date:23
Once sent through flatten
const flatten = async { let flatFoo = await }
Becomes an object like this:
flatFoo = '$.name': 'bob' '$.datas.some.foos': true '$.datas.rayray[0].nested.rayray[0]': true '$.datas.rayray[0].nested.rayray[1]': false '$.nestedArrays[1][0]': 2 '$.nestedArrays[2][0]': 3 '$.nestedArrays[0][0].date': 'DATE_2020-06-13T22:28:37.625Z'
It can be converted back to it's original state like this:
const inflate = async { const foo = await }
These functions work the same for an array as the root element
async { const array = 1two:23 const flatArray = const inflatedArray = }
Custom Serialization/Deserialization of values
In some cases you may want to avoid traversing an object and instead convert the object or array to a value.
For instance, Dates being converted to iso strings.
To use this feature, pass an array of serializers to the flatten method or an array of deserializers to the inflate method.
A serializer must implement two methods, canSerialize and serialize. Async functions are supported.
CanSerialize should return a boolean to determine if this value can be handled. serialize should return the serialized value.
Serialize is called before traversing object keys so complex objects can be converted to simple values.
The pathParts are provided for reference in cases where information is stored in the keys
const serializer = o instanceof Date `DATE_` continue: true async { const inflatedArray = }
the reference to pathParts is the actual working array for the recursive traversal, thus you can modify the path objects here along with the value before it's written to the result.
If a path is modified, you will need to use a custom pathExpander to undo the modifications to ensure deserialization works.
Likewise, a deserializer must implement two methods, canDeserialize and deserialize
const deserializer = s `DATE_` continue: false async { const inflatedArray = }
The continue property determines if this serializer should be the final serializer for the value, or if other serializers are allowed to serialize the produced value. This is useful for chaining serializations.
Custom Serialization/Deserialization of paths
To specify a custom way to generate paths for each value, pass a function as the third argument to flatten or inflate.
These functions are called the pathReducer and pathExpander.
During flattening, the current path is represented as an array of objects, each with two properties: key and isInd
key: 'foo' isInd: false
The key is the property name or index of the current part of the path, and isInd specifies whether the key represents an array index or object property.
The first element in the array is always the root element represenation of
key: '$' isInd: false
The pathReducer should take this array of property objects and convert them to a single path.
The expand function undoes this operation, it takes a single path and expands it back to the array of objects representing the path.
The following rule must always hold (assume == is deep equals by value equality not reference equality)
let pathParts = key:'$' isInd: false key:'foo' isInd: false key:'0' isInd: truepathParts ==