Giter Site home page Giter Site logo

dto_derive's Introduction

#[derive(Dto)]

Build Status

This crate provides Dto derive automating the process of mapping DTOs (Data Transfer Objects) into Entities and vice versa. It is capable of implementing From or Into traits for DTO structures regarding conversion direction.

Every DTO structure can act as a request or a response, which means that particular DTO structure can be converted either from an Entity or into an Entity. Therefore, a DTO which should be convertible into an Entity is a request DTO and a DTO which should be built from an Entity is a response DTO.

In addition to a simple one-to-one conversion, the crate allows skipping particular fields or renaming them during conversion process. More advanced features, like for example, assigning an external values or field-level attributes are planned for next releases.

Installation and basic usage

Add the following dependency to Cargo.toml:

[dependencies]
dto_derive = "0.1.0"

Then import Dto derive by:

use dto_derive::Dto;

And use it like so:

struct Post {
  ...
}

#[derive(Dto)]
#[dto(entity = "Post")]
struct PostResponse {
  ...
}

That enables you to convert Post into PostResponse in this case:

let post: Post = ...;
let post_response: PostResponse = post.into();

For more examples and use cases check sections below.

Derive associated attributes

  • #[dto(entity = "Entity")]

    Required attribute containing a type of a mapped entity. It has to be provided exactly once per DTO structure.

  • #[dto(request)], #[dto(response)]

    Optional attributes specifying a conversion direction, can be omitted when DTO structure name ends with ...Request or ...Response, e.g., PostResponse, otherwise have to be provided.

  • #[dto(map = "a: b")]

    Optional attribute telling how to rename field names during conversion. It may be repeated for different fields.

  • #[dto(skip = "a, b, c")]

    Optional attribute containing field names which should be omitted during conversion. It may contain multiple fields to skip and/or it may by repeated for different fields. The attribute is only valid for request DTOs.

Examples

Let's start with our Post entity implementation:

struct Post {
    title: String,
    body: String,
}

Request DTO

In order to create a new post we may have a DTO representation:

#[derive(Dto)]
#[dto(entity = "Post")]
#[dto(request)]
#[dto(map = "body: content")]
#[dto(skip = "csrf_token")]
struct NewPost {
    title: String,
    content: String,
    csrf_token: String,
}

Above DTO may be converted to the Post entity using into() function from Into trait:

let newPost = NewPost {
    title: String::from("Awesome post"),
    content: String::from("Awesome content of awesome post."),
    csrf_token: String::from("abcde"),
};

let post: Post = newPost.into();

It is possible because NewPost DTO is implementing Into trait due to Dto derive.

Response DTO

Response DTO may look like:

#[derive(Dto)]
#[dto(entity = "Post")]
#[dto(map = "content: body")]
struct PostResponse {
    title: String,
    content: String,
}

The conversion from entity to PostResponse DTO may be done using into() function from Into trait:

let post = Post {
    title: String::from("Awesome post"),
    body: String::from("Awesome content of awesome post."),
};

let postResponse: PostResponse = post.into();

It is possible because PostResponse DTO is implementing From trait due to Dto derive.

Under the hood

Adding #[derive(Dto)] attribute means providing automatic implementation of From or Into trait for a given structure.

Thus, for the NewPost DTO structure and the Post entity (from previous section), below implementation will be automatically provided (notice the request nature of the NewPost DTO):

impl Into<Post> for NewPost {
    fn into(self) -> Post {
        Post {
            title: self.title,
            body: self.content,
        }
    }
}

The opposite implementation will be derived for the PostResponse DTO which is in fact a response DTO:

impl From<Post> for PostResponse {
    fn from(entity: Post) -> Self {
        PostResponse {
            title: entity.title,
            content: entity.body,
        }
    }
}

It is worth noting that a derive implementation is always provided for DTO structures which allows to import entity structures from another crate without breaking the orphan rule.

License

Licensed under the MIT license (LICENSE or https://opensource.org/licenses/MIT).

dto_derive's People

Contributors

mb1986 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.