Converting data from one object to another in code is an incredibly mundane task, but it comes with the territory as an enterprise developer working in large databases.

Recently, I have found a TypeScript implementation of AutoMapper that has become my go-to for performing data conversions. Paring AutoMapper with a CSV parser, as a way to enhance a payload, has been invaluable on recent projects.

What is AutoMapper?

AutoMapper (.NET) is part of the standard toolkit in enterprise .NET development and serves as a great way to abstract code needed to convert from one class to another. This is especially useful when using Data Transfer Objects (DTOs) .

Simple mappings, such as:

  • Copy directly from the input DTO to the type expected by the business layer (1-for-1 copy of properties).
  • Break down a simple object into multiple parts.
  • Break down objects of objects for saving to various tables or collections.  

More complex mappings can be used to:

  • Create trimmed down versions of more complex objects, removing unnecessary properties.
  • De-normalize flat objects, such as those coming from CSV files or database rows.  
  • Perform enhancements to add data during the transformation process.

Using a mapping profile

AutoMapper allows the transformation logic to be decoupled from the classes and services that use AutoMapper by establishing mapping profiles to command and specify the source and destination data types.

const result = this.mapper.map(order, Order, OrderDto);

A mapping profile is made up of a few parts. The createMap command defines the source, destination, and options for the mapping.

The mapping profile rules how individual properties on the target (destination) are created. These rules take several forms. The can be explicit (example below) or they can be generated using the @AutoMap decorator.

Conditional logic can also be used to control the mappings.

mapProfile(): MappingProfile {
  return (mapper: Mapper) => {
    mapper
      .createMap(OrderDto, Order, {})
      .forMember(
        (dest) => dest.paid,
        mapFrom((src) => { 
          if (src.status == 'paid') return true;
          return false;
        })
      )
      //...
  }
}

Getting started

Getting AutoMapper up and running with NestJS is fairly easy.

Step one, install the following packages from NPM, Yarn, or your package manager of choice.

npm install @automapper/{core, classes, nestjs} class-transformer class-validator
npm install --save-dev @automapper/types

Step two, add the AutoMapper module to your application using some initial setup parameters.

import { classes } from '@automapper/classes';
import { AutomapperModule } from '@automapper/nestjs';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    AutomapperModule.forRoot({
      options: [{ name: 'classes', pluginInitializer: classes }],
      singular: true,
    }),
    TacoModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Once the setup is complete, adding Automapper to other modules is simple.

Next, import the Automapper module (with-out configuration) and then add any profiles to the list of providers. If they are to be used externally, add them to the exports as well.

import { AutomapperModule } from '@automapper/nestjs';
import { Module } from '@nestjs/common';
import { TacoService } from '.';
import { TacoProfile } from './profile';

@Module({
  imports: [AutomapperModule],
  providers: [TacoService, TacoProfile],
})
export class TacoModule {}

Conclusion

With your Automapper configured and some simple profiles setup, you'll be able to map objects from DTO to the business object with ease. No more having to hunt down transformation logic in multiple places when something changes.

Looking for a playground to get started? Check out this reference implementation.

At Tevpro, we work with companies of all shapes and sizes to automate and optimize business processes.  I hope you found this article helpful and if you have any other coding challenges, feel free to reach out on Twitter or via email with any questions.


Photo by Alvaro Reyes