
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
auto-mapping
Advanced tools
Map and convert objects automatically in typescript.
$ npm install --save auto-mapping
Please import the reflect-metadata module in the project entry file before use.
To enable experimental support for decorators, you must enable the experimentalDecorators compiler option either on the command line or in your tsconfig.json:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
}
}
import 'reflect-metadata';
import { mapping, map, select } from 'auto-mapping';
class Person {
@mapping({ type: String })
name: string;
@mapping(Boolean) // short form
gender: boolean;
@mapping({ path: 'others.number', type: Number })
age: number;
extraData = 1;
}
const data={
name: 'fisher',
gender: 1,
others: { number: '18' },
};
console.info("Mapped result:", map(data, Person));
console.info("Selected result:", select(data, Person));
# output
Mapped result: Person { extraData: 1, name: 'fisher', gender: true, age: 18 }
Selected result: { name: 'fisher', gender: true, age: 18 }
If you have already imported reflect-metadata module into your project, it will infer type automatic except array type. The array type must declare the type parameter at any time.
import 'reflect-metadata';
import { mapping, map } from 'auto-mapping';
class Person {
@mapping()
name: string;
@mapping()
gender: boolean;
@mapping({ path: 'others.number' })
age: number
}
const data={
name: 'fisher',
gender: 1,
others: { number: '18' },
};
console.info(map(data, Person));
# output
Person { name: 'fisher', gender: true, age: 18 }
Configuring property mapping information, If the argument is a function, then it is equivalent to { type: options }.
Map an object to an instance of the specified type.
Set the global conversion function for the specified type
The function setDefaultConverter will affect the global type conversion. If you want to use it locally, please set the converters option of the map function.
import "reflect-metadata";
import { mapping, map } from "auto-mapping";
map.setDefaultConverter(String, (val) => (val === undefined || val === null) ? '' : String(val));
map.setDefaultConverter(Number, (val) => isNaN(Number(val)) ? 0 : Number(val));
class Person {
@mapping()
public cityName: string;
@mapping(() => "default")
public intro: string;
@mapping()
public num: number;
}
console.info(map({}, Person));
# output
Person { name: '', desc: 'default', num: 0 }
Because the type of the array cannot be automatically derived, the type parameter must be specified at all times and the value must be an array.
import { mapping, map } from 'auto-mapping';
class ArrayTest {
@mapping({ type: [Number] })
numbers: number[];
}
const data={
numbers:['1','2','3']
};
const result = map(data, ArrayTest);
console.info(result);
# output
ArrayTest { numbers: [ 1, 2, 3 ] }
If an property is declared as array, but the source value is not an array, the result is wrapped into an array.
import { mapping, map } from 'auto-mapping';
class ArrayTest {
@mapping({ type: [Number], path:'number' })
numbers: number[];
}
const data={
number: '1'
};
console.info(map(data, ArrayTest));
# output
ArrayTest { numbers: [ 1 ] }
The default data source mapping config named default, you can set multiple configurations by source option to map multiple data sources.
import { mapping, map } from 'auto-mapping';
class Person {
@mapping()
@mapping({ source: 'other', path: 'person.name' })
name: string;
}
const dataSource1 = {
name: 'fisher'
};
const dataSource2 = {
person: { name: 'jack' }
};
const result1 = map(dataSource1, Person);
const result2 = map(dataSource2, Person, { source: 'other' });
console.info(result1, result2);
# output
Person { name: 'fisher' } Person { name: 'jack' }
The signature of the custom conversion function is as follows:
function(value: any, source: any, dest: any, options?: object){}
Custom conversion function can be set by type parameter. If you just pass a function to the annotation, like this mapping(fn), then it is equivalent to mapping({ type: fn }).
import { mapping, map } from 'auto-mapping';
function trim(value: string) {
return value && value.trim();
}
function fullName(_value: any, source: any) {
return `${source.firstName} ${source.lastName}`;
}
function info(_value: any, _source: any, dest: Person) {
return `I am ${dest.name} who come from ${dest.city}`;
}
class Person {
age: number = 18;
@mapping(fullName)
name: string;
@mapping({ type: trim, path: 'city.cityName' })
city: string;
@mapping(info)
info: string;
}
const dataSource = {
firstName: 'Lei',
lastName: 'Lee',
city: {
cityId: 1,
cityName: ' NEW YORK '
},
};
console.info(map(dataSource, Person));
# ouput
Person {
age: 18,
name: 'Lei Lee',
city: 'NEW YORK',
info: 'I am Lei Lee who come from NEW YORK.'
}
Do some processing before mapping.
import "reflect-metadata";
import { mapping, map, MAPPING } from "auto-mapping";
class Person {
@mapping()
public num: number = 1;
@mapping()
public name: string;
[MAPPING](src: any, options: any) {
src.name = "fisher";
}
}
const result = map({ num: 10 }, Person);
console.info(result, result instanceof Person);
# output
Person { num: 100, name: 'fisher' } true
If the MAPPING function returns a value that is not undefined, it will be passed to the map method as a source object.
Sometimes you may need to do some extra finishing work, such as dynamically adding some properties, you can do this through the MAPPED symbol function.
import "reflect-metadata";
import { mapping, map, MAPPED } from "auto-mapping";
class Person {
@mapping()
public gender: boolean;
@mapping()
public num: number = 1;
[MAPPED](src: any, options: any) {
// set value manually
this.gender = true;
// override original value
this.num = 100;
// dynamic assignment
Object.assign(this, { a: 1, b: 2 })
}
}
const result = map({ num: 10 }, Person);
console.info(result, result instanceof Person);
# output
Person { num: 100, gender: true, a: 1, b: 2 } true
:warning: Note that when using the MAPPED function, if the map result is null, then any property that accesses this will throw an error.
If the function returns a value that is not undefined, it will replace the map result value.
...
[MAPPED](src: any, options: any) {
this.gender = true;
this.num = 100;
return Object.assign({}, this, { a: 1, b: 2 })
}
...
# output
{ num: 100, gender: true, a: 1, b: 2 } false
select function.FAQs
map and convert object in typescript
The npm package auto-mapping receives a total of 47 weekly downloads. As such, auto-mapping popularity was classified as not popular.
We found that auto-mapping demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.