Reputation: 33
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
Reputation: 23226
The simplest way is to control the serialization to JSON via the annotations provided by the default JSON library which is Jackson.
@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
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
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
Reputation: 77167
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
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
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
Reputation: 922
So, there are 2 different ways you can approach this problem.
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.
@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