{"id":17772156,"url":"https://github.com/dranikpg/dto-mapper","last_synced_at":"2025-04-21T23:31:06.445Z","repository":{"id":37590393,"uuid":"448910778","full_name":"dranikpg/dto-mapper","owner":"dranikpg","description":"go library for complex struct mapping","archived":false,"fork":false,"pushed_at":"2024-01-27T17:27:21.000Z","size":26,"stargazers_count":81,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-01T16:55:51.429Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dranikpg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-17T13:45:19.000Z","updated_at":"2025-02-16T16:28:26.000Z","dependencies_parsed_at":"2024-01-27T18:30:59.188Z","dependency_job_id":"60eb4b92-32c7-4239-85d7-081dcdfd1c99","html_url":"https://github.com/dranikpg/dto-mapper","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dranikpg%2Fdto-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dranikpg%2Fdto-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dranikpg%2Fdto-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dranikpg%2Fdto-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dranikpg","download_url":"https://codeload.github.com/dranikpg/dto-mapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250150631,"owners_count":21383201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-26T21:38:08.162Z","updated_at":"2025-04-21T23:31:06.167Z","avatar_url":"https://github.com/dranikpg.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Dto mapper\n\n\u003ca href=\"https://pkg.go.dev/github.com/dranikpg/dto-mapper\"\u003e\u003cimg src=\"https://godoc.org/github.com/dranikpg/dto-mapper?status.svg\" /\u003e\u003c/a\u003e\n[![Go Report Card](https://goreportcard.com/badge/github.com/dranikpg/dto-mapper?fix-cache-1)](https://goreportcard.com/report/github.com/dranikpg/dto-mapper)\n\ndto-mapper is an easy-to-use library for complex struct mapping. It's intended for the creation of [data transfer objects](https://en.wikipedia.org/wiki/Data_transfer_object), hence the name.\n\nWhen 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_.\n\ndto-mapper 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!\n\n### Simple example\n\nYou just have to declare the values you want to extract and dto does the rest.\n\n```go\nfunc GetUserPosts(c *gin.Context) {\n    var userDto struct {\n        Name  string\n        Posts []struct {\n          Id    int\n          Title string\n        }\n    }\n    userModel := LoadUserWithPosts(userId)\n    dto.Map(\u0026userDto, userModel)\n    c.JSON(200, userDto)\n}\n```\n\n### Installation\n\n```\ngo get github.com/dranikpg/dto-mapper\n```\n\n### More examples\n\n##### Slices, maps and structs\n\ndto works its way down recursively through struct fields, slices and maps.\n\n```go\nvar shoppingCart struct {\n    GroupedProducts map[string][]struct {\n        Name      string\n        Warehouse struct {\n            Location string\n        }\n    }\n}\n```\n\nMaps can be converted into slices of their values. \nWhat's more, a map of slices can be converted into a single slice.\n\n```go\nvar allProducts []Product = nil\nvar groupedProducts map[string][]Product = GetProducts()\ndto.Map(\u0026allProducts, groupedProducts)\n```\n\n##### Emedded structs and pointers\n\nEmbedded struct fields are included. Pointers are automatically dereferenced.\n\n```go\ntype User struct {\n    gorm.Model\n    CompanyRefer int\n    Company      *Company `gorm:\"foreignKey:CompanyRefer\"`\n}\n\ntype UserDto struct {\n    ID      int\n    Company struct {\n        Name string\n    }\n}\n```\n\n##### Ignored fields\n\nIf you need to ignore any of the structure fields, you can apply the structure tag - dto:ignore\n\n```go\ntype Order struct {\n\tId string\n\n\tjson.Marshaler   `dto:\"ignore\"`\n\tjson.Unmarshaler `dto:\"ignore\"`\n}\n\ntype OrderDto struct {\n\tId string\n}\n```\n\n#### Mapper instances\n\nLocal 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.\n\n```go\nmapper := dto.Mapper{}\nmapper.Map(\u0026to, from)\n```\n\n##### Conversion functions\n\nThey are used to convert one type into another and have the highest priority, however they are not applied to fields of directly assignable structs. The second argument is the current mapper instance and is optional.\n\n```go\nmapper.AddConvFunc(func(p RawPassword, mapper *Mapper) PasswordHash {\n    return hash(p)\n})\n```\n\n##### Inspection functions \n\nThose are triggered _after_ a value has been successfully mapped. The value is **always taken by pointer**. Likewise to conversion functions, they are not called for fields of directly assignable structs.\n\n```go\nmapper.AddInspectFunc(func(dto *UserDto) {\n    dto.Link = GenerateLink(dto.ID)\n})\n```\n\nThey can also be defined with a specific source type. The last argument is optional.\n\n```go\nmapper.AddInspectFunc(func(dto *UserDto, user User, mapper *Mapper) {\n    dto.Online = IsRecent(user.LastSeen)\n})\n```\n\n##### Error handling\n\n* Both conversion and inspection functions can return errors by returning `(value, error)` and `error` respectively\n* If dto failed to map one value onto another, it returns `ErrNoValidMapping`\n* dto silently skips struct fields it found no source for (i.e. no fields with the same name)\n\nMapping stops as soon as an error is encountered.\n\n```go\nmapper.AddInspectFunc(func(dto *UserDto) error {\n    if len(dto.Link) == 0 {\n        return errors.New(\"malformed link\")\n    }\n    return nil\n})\n\nerr := mapper.Map(\u0026to, from) // error: malformed link\n```\n\n### Performance\n\nDto is based on reflection and therefore much slower than handwritten mapping code. \nFurthermore, using custom functions disables direct assignment of composite types. \n\n### Contributing\n\nMissing a common use case? Feel free to contribute!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdranikpg%2Fdto-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdranikpg%2Fdto-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdranikpg%2Fdto-mapper/lists"}