github.com/dranikpg/go-dto@v1.0.0/README.md (about)

     1  ## go-dto
     2  
     3  go-dto is an easy-to-use library for data mapping. It is intended for the creation of [data transfer objects](https://en.wikipedia.org/wiki/Data_transfer_object), hence the name.
     4  
     5  When working with database relations and ORMS, you often fetch more data than needed. One could create subtypes for all kinds of queries, but this is not suitable for quick prototyping. Tools like [go-funk](https://github.com/thoas/go-funk) and [structs](https://github.com/fatih/structs) make your mapping code less verbose, but _you still have to write it_.
     6  
     7  go-dto requries __only a declaration__ and contraty to many other struct mappers uses __only name-based field resolution__, works with __arbitrary deep__ structures, slices, maps, poiners, embedded structs, supports custom conversion functions, error handling... you name it!
     8  
     9  ### Simple example
    10  
    11  You just have to declare the values you want to extract and go-dto does the rest.
    12  
    13  ```go
    14  func GetUserPosts(c *gin.Context) {
    15      var userDto struct {
    16          Name  string
    17          Posts []struct {
    18            Id    int
    19            Title string
    20          }
    21      }
    22      userModel := LoadUserWithPosts(userId)
    23      dto.Map(&userDto, userModel)
    24      c.JSON(200, userDto)
    25  }
    26  ```
    27  
    28  ### Installation
    29  
    30  ```
    31  go get github.com/dranikpg/go-dto
    32  ```
    33  
    34  ### More examples
    35  
    36  ##### Slices, maps and structs
    37  
    38  go-dto works its way down recursively through struct fields, slices and maps.
    39  
    40  ```go
    41  var shoppingCart struct {
    42      GroupedProducts map[string][]struct {
    43          Name      string
    44          Warehouse struct {
    45              Location string
    46          }
    47      }
    48  }
    49  ```
    50  
    51  A map of slices can be converted into a single slice.
    52  
    53  ```go
    54  var allProducts []Product = nil
    55  var groupedProducts map[string][]Product = GetProducts()
    56  dto.Map(&allProducts, groupedProducts)
    57  ```
    58  
    59  ##### Emedded structs and pointers
    60  
    61  Embedded struct fields are included. Pointers are automatically dereferenced.
    62  
    63  ```go
    64  type User struct {
    65      gorm.Model
    66      CompanyRefer int
    67      Company      *Company `gorm:"foreignKey:CompanyRefer"`
    68  }
    69  
    70  type UserDto struct {
    71      ID      int
    72      Company struct {
    73          Name string
    74      }
    75  }
    76  ```
    77  
    78  #### Mapper instances
    79  
    80  Local mapper instances can be used to add conversion and inspection functions. Mappers don't change their internal state during mapping, so they can be reused at any time.
    81  
    82  ```go
    83  mapper := dto.Mapper{}
    84  mapper.Map(&to, from)
    85  ```
    86  
    87  ##### Conversion functions
    88  
    89  They are used to convert one type into another. Conversion functions have the highest priority. The second argument is the current mapper instance and is optional.
    90  
    91  ```go
    92  mapper.AddConvFunc(func(p RawPassword, mapper *Mapper) PasswordHash {
    93      return hash(p)
    94  })
    95  // Now mapper knows how to convert a RawPassword into a PasswordHash
    96  ```
    97  
    98  ##### Inspection functions 
    99  
   100  Those are triggered _after_ a value has been successfully mapped. The value is **always taken by pointer**.
   101  
   102  ```go
   103  mapper.AddInspectFunc(func(dto *UserDto) {
   104      dto.Link = GenerateLink(dto.ID)
   105  })
   106  ```
   107  
   108  They can also be defined with a specific source type. The last argument is optional.
   109  
   110  ```go
   111  mapper.AddInspectFunc(func(dto *UserDto, user User, im *Mapper) {
   112      dto.Online = IsRecent(user.LastSeen)
   113  })
   114  ```
   115  
   116  ##### Error handling
   117  
   118  * Both conversion and inspection functions can return errors by returning `(value, error)` and `error` respectively
   119  * If go-dto failed to map one value onto another, it returns `ErrNoValidMapping`
   120  * go-dto silently skips struct fields it found no source for (i.e. no fields with the same name)
   121  
   122  Mapping stops as soon as an error is encountered.
   123  
   124  ```go
   125  mapper.AddInspectFunc(func(dto *UserDto) error {
   126      if len(dto.Link) == 0 {
   127          return errors.New("malformed link")
   128      }
   129      return nil
   130  })
   131  
   132  err := mapper.Map(&to, from)
   133  ```
   134