Anish
Anish

Reputation: 33

How to return only few types from Class using spring boot?

I have a class that has users information including the password field. When the user login, it will return everything from class including password. How do I not return everything from class except the password or any important data that only remain in the database.

I tried using the Map this also returns the way I want but I was hoping if there is something easier or quicker then Map.

There are few answers suggesting using JsonIgnore and transient. If I use these two methods, I am not able to login. Because I need password back for login.

My POJO Class

@Entity
public class Users {

@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;

@Column(name = "firstname")
private String firstName;

@Column(name = "lastname")
private String lastName;

@Id
@Column(name = "username")
private String username;

@Column(name = "email")
private String email;

@Column(name = "role")
private String role;

@Column(name = "password")
private String password;

Repo Class

  public interface UsersRepository extends CrudRepository<Users, 
  String> {

public Users findByUsername(String username);
}

this is Rest Api

@GetMapping("/users/{username}")
public Map<String, Object> usersCheck(@PathVariable String 
 username) {
    Map<String, Object> addUser = new HashMap<>();
    Users user = userRepo.findByUsername(username);
    addUser.put("email", user.getEmail());
    addUser.put("firstName",user.getFirstName());
 "
 "
    return addUser;
}

Is there a better way then Map. Any suggestion can be helpful.

Upvotes: 0

Views: 2856

Answers (7)

Alan Hay
Alan Hay

Reputation: 23226

The simplest way is to control the serialization to JSON via the annotations provided by the default JSON library which is Jackson.

https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonIgnore.html

@JsonIgnore
@Column(name = "password")
private String password;

You can also do this via a Jackson mixin to avoid 'polluting' the entity with JSON processing instructions.

Upvotes: 1

GnanaJeyam
GnanaJeyam

Reputation: 3170

If you want to exclude password from the response then annotate the password field with @JsonIgnore.

If you want to exclude more than one field in the User entity then create an UserDto class and add the required field in that UserDto class.

Use ModelMapper to map the User entity to UserDto class. Finally return this UserDto class as a response object.

Example:

  User user = new User();

  UserDto userDto = new ModelMapper.map(user, UserDto.class);

This will include the fields in UserDto only

Upvotes: 0

peterzinho16
peterzinho16

Reputation: 989

Another solution could be create a method in repository with @Query annotation like:

@Query("SELECT NEW MyEntity(M.firstName, M.lastName, M.email) FROM MyEntity M WHERE M.username = ?1")
public MyEntity getByUsername(String username);

Then in your MyEntity class create a constructor that matching with query's constructor.

By last, in your controller:

Instead of:

public Map<String, Object> usersCheck(@PathVariable String 
 username)

Do:

public MyEntity usersCheck(@PathVariable String 
 username){
   return userRepo.getByUsername(username);
}

Return directly cause spring have a naturally integration with Jackson serialization so by default your response will be a json object

I think this solution is a good alternative in your case.

Upvotes: 0

The typical best practice here is to treat the password as a subresource: logically not a direct part of the User resource, but related to it (e.g., it might have its own URL at /users/{id}/password). Spring Data REST handles this automatically when you have a JPA @OneToOne relationship, but there's no problem with doing it yourself.

This example shows why it is not a good idea to use your @Entity classes directly as the JSON API representations, because you may want to have differences internally (including making changes in the future without disturbing clients). Instead, use a data transfer object (DTO) that serves as a "JSON copy" of your entity. Tools like MapStruct make it very simple to copy properties between User and UserDto.

(Finally, if you do find yourself needing to return a bare Map for some odd reason, which does happen, it's typically best to use Map.of("key", value) for simplicity.)

Upvotes: 0

AK DevCraft
AK DevCraft

Reputation: 81

Apart from already mentioned reply, few other ways are also there such as JsonIgnoreProperties, JsonIgnoreType, JsonFilter. I prefer JsonIgnore for suppressing the field in the output.

Here is a link to nice example https://www.baeldung.com/jackson-ignore-properties-on-serialization

Also, you can always create a separate POJO class to return desire values.

Upvotes: 0

Alien
Alien

Reputation: 15878

Actually there is a way in jpa queries To return only specific field so you can use directly while fetching the results.

But in case if you don't want to disturb the findByUsername method than just create an object of User class and set only desired fields.

The approach you are using currently is also feasible solution.

Upvotes: 1

Ankur
Ankur

Reputation: 922

So, there are 2 different ways you can approach this problem.

  1. Make password field transient in your Entity class.

This way, when you fetch the Users object, password field would be blank.

Disadvantage : Making password transient would result in the fact that you would not be able to get password via you entity anywhere in your application.

  1. Use @JsonIgnore(from jackson library) over password field. This way, when you return the object of Users object, password field would be ignored.

Disadvantage : This would again means that if ever you want to take password field as input or return password field through out the application you would not be able to do so. Also, it is not recommended that you return object of your POJO class ever as response.

So, you can go with either one keeping in mind the disadvantages each approach has.

Upvotes: 0

Related Questions