Library to extract one JSON data structure from another
npm install @jungehaie/extractormapExtractorMap is a utility library to extract the properties of an input object
and map those to a given new structure, allowing for transformation of those properties
in the process.
``bash`
$ npm install --save @jungehaie/extractormap
An Extractor map `ExtractorMap` of a type `T` has the same `keys` as`T` but for every value provides a function extracting the corresponding value of `T` from a given input of type `S`.
An `ExtractorMap` is therefore specific to the `source` of the data as well as`
to the type of the resulting object T`.
From the type defintion you can see you can omit the type of the input `S` can be omitted, which will result in less typesafety.
Given a target type `T`:
`typescript`
{
"foo": number,
"bar": string
}
and an input (`S`)
`json`
{
"qux": 1,
"quux": "2",
}
An `ExractorMap` could be
`typescript`
{
"foo": (input: S) => input['qux'],
"bar": (input: S) => input['quux']
}
The library provides two ways to extract the target object from the structure:
#### `extract``
Returns an eagerly constructed object of type T` that is returnded from `extract`.
#### `createExtractingProxy``
Returns a proxy object of type T` which allows for accessing the properties of `T via getter. The proxy
extracts the values on demand therefore will appear as an empty object when access as whole.
Given the three objects given above one could do the following:
`typescript`
const target: T = extract
Hint: `extract` and `createExtractingProxy` can also be called in curried form.
In addition there is a version of extract that allows for filtering values that are defined as empty:
#### `extractFilteringEmptys``
Returns an eagerly constructed object of type T` that is returnded from `extractFilteringEmptys`. Any value`
contained in valuesInterpretedasEmpty` will result in the corresponding key not being present in the resulting
object.
To simplify the construction of ExtractorMaps the library also provides some helper functions:
#### `jpv` `
Given a json path` and an optional result transformer which defaults to the identity function, returns a function that returns the first (transformed) matching properites value.`
#### jpq` `
Given a json path` `
and an optional result transformer which defaults to the identity function, returns a function that returns an
array of all (transformed) properties value that match.
#### jpa`: `
Given a json path` `
and an optional result transformer which defaults to the identity function, returns a function that returns a
(transformed) array of all properties value that match.
#### constant`: `
Will return a function returning the given constant disregarding the input object completely.
#### pickMapGenerator`
Will return an ExtractorMap that extracts the untransformed value of any key contained in the keys array and puts this value under the key by the same name in the output object.
Given those helper functions the ExtractorMap from above could have been written as:
`typescript`
{
"foo": jpv('qux'),
"bar": jpv('quux')
}
another `ExtractorMap` could be.
`typescript`
{
"foo": jpv('quux', x => parseInt(x, 10)),
"bar": constant('Quux')
}
In addition to the given functions above there are the followinn converter functions
#### `identity`:`
Returning the input as output. Ususally only necessary as the default value for the convert function in jpv`, `jpq`, `jpa`, but might be of use to construct your own ExtractorFunction helper.`
#### defaultTo``
Returning T if the previous result is a value provided in the forVals`. If no `forVals` are provided`
only undefind` will be used.
Since using `jpv("jsonpath")` is by far the most used function there is a shortcut. As long as you don't need a conversion function you can just write the given jsonpath as a string.
So this `ExtractorMap`
`typescript`
{
"foo": jpv('qux'),
"bar": jpv('quux')
}
is equivalent to this `ExtractorMap`
`typescript`
{
"foo": 'qux',
"bar": 'quux'
}
If you provide a definition of your source type all functions where this is possible (e.g. `jpv` and directly providing a `jsonpath`) will provide type ahead and type checking for the jsonpath such that only pathes to correct type of your source object are allowed.
`typescript`
{
foo: number,
bar: {
first: string,
second: number
}
}
We don't necessarily need to write the following `ExtractorMap` like this:
`typescript`
{
foo: jpv('qux'),
bar: jpv('quux')
}
but could use the following nested structure.
`typescript``
{
foo: jpv('qux'),
bar: {
first: jpv('quux.first'),
second: jpv('quux.second')
}
}
This ist obviously more helpful should the source need to be transformed.