/mapperx

Simple and fast mapper library tool with heavily utilized code generation.

Primary LanguageGo

MapperX

MapperX

Motivation

     As a firm believer, I strongly emphasize things with separation of concerns. If you look into countless go repositories, you will see unstructured models with no aim to distinguish between request and response models. Further way things get more bizarre and I see entities(database models) dumped into a single model package where every request, response models exist. I have seen countless times people are super lazy to create separate entity - DTO(data transfer object) structs then they end up with exposing entity struct to end user via REST API including relational database IDs. This is generally due to laziness of creating a new struct which could be response struct with omitted fields. I can not blame the laziness sometimes if you have a thousand of properties, it is actually really annoying to map something from request to your database model then your database model to response. This is where I thought I need a powerful yet so simple mapper codegen for too many fields

What we aim to do

  • 1-to-1 struct-struct mapping
  • Maps underlying nested slices, maps, structs
  • Maps same types with same variable names by default
  • Maps same types with different names by tag specification in source struct
  • Does use reflection to generate mapperx package at compile time

What we don't aim to do

  • Doesn't aim to do aggregation while mapping
  • Doesn't map not equal types
  • Doesn't use reflection at runtime

Getting Started

   Mapperx heavily relies on code generation. This means that you need to specify 3 flag arguments source(file path and struct type) and target(file path and struct type) and output(output directory) Then mapperx will generate a directory and a package called mapperx, when you run it. The Easiest way to use is to do go generate compiler directive in your definitions at the start of a file.

go get -u github.com/MrWormHole/mapperx
package main

//go:generate go run github.com/MrWormHole/mapperx -source=github.com/MrWormHole/mapperx/examples/model.Admin -target=github.com/MrWormHole/mapperx/examples/model.User -directory=../mapperx -filename=XXX_ADMIN_TO_USER_XXX
// OR
///go:generate go run github.com/MrWormHole/mapperx -source=github.com/MrWormHole/mapperx/examples/model.Admin -target=github.com/MrWormHole/mapperx/examples/model.User

type troll bool

type Admin struct {
	Name        string
	ID          string
	Country     string
	Score       string `mapperx:"Highscore"`
	troll 	    troll
	Friends     []string
	Permissions map[string]string `mapperx:"GivenPermissions"`
	Minion *Minion
}

type User struct {
	Name            string
	ID              string
	Country         string
	Highscore       string
	troll 	        troll
	Friends         []string
	GivenPermissions map[string]string
	Minion *Minion
}

Output file will look something like this

// Code generated by mapperx, PLEASE DO NOT EVER EDIT. GENERATATED AT 2021-06-22 10:14:21.5543809 +0100 BST m=+0.393255201
package mapperx

import model "github.com/MrWormHole/mapperx/examples/model"

func AdminToUser(admin *model.Admin, user *model.User) {
	user.Name = admin.Name
	user.ID = admin.ID
	user.Country = admin.Country
	user.Highscore = admin.Score
	user.Friends = make([]string, len(admin.Friends))
	copy(user.Friends, admin.Friends)
	user.GivenPermissions = make(map[string]string, len(admin.Permissions))
	for k, v := range admin.Permissions {
		user.GivenPermissions[k] = v
	}
	user.Minion = admin.Minion
}