Json 在@SpringBootTest中,如何让fasterxml对象映射器包含模型中的字段?
我正在使用SpringBoot2.1和Java11。我已经用fasterxml注释了我的用户模型,这样我的密码可以被POST请求接受,但不会被其他REST请求返回Json 在@SpringBootTest中,如何让fasterxml对象映射器包含模型中的字段?,json,spring,spring-boot-test,fasterxml,spring-boot-2,Json,Spring,Spring Boot Test,Fasterxml,Spring Boot 2,我正在使用SpringBoot2.1和Java11。我已经用fasterxml注释了我的用户模型,这样我的密码可以被POST请求接受,但不会被其他REST请求返回 @Data @Entity @Table(name = "Users") public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID
@Data
@Entity
@Table(name = "Users")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String firstName;
private String lastName;
@NotBlank(message = "Email is mandatory")
@Column(unique=true)
private String email;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
private boolean enabled;
private boolean tokenExpired;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(
name = "role_id", referencedColumnName = "id"))
private Collection<Role> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getUsername() {
return email;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return false;
}
@PrePersist @PreUpdate
private void prepare(){
this.email = this.email.toLowerCase();
}
}
当从读取端点请求我的实体时,如何正确地将我的密码作为映射的一部分包括在内,并禁止使用密码?这是一个常见的误解,甚至有一个错误 “读”和“写”是从Java属性的角度来理解的,即,当序列化对象时,必须读取该属性,当反序列化该属性时,必须写入该属性
在您的情况下,您想要
@JsonProperty(access=JsonProperty.access.READ_ONLY)
这是一个常见的误解,甚至有一个错误
“读”和“写”是从Java属性的角度来理解的,即,当序列化对象时,必须读取该属性,当反序列化该属性时,必须写入该属性
在您的情况下,您需要@JsonProperty(access=JsonProperty.access.READ_ONLY)
- 使用
或WRITE\u ONLY
在您的情况下不起作用。原因是http上的一个调用需要两者。让我们以READ\u ONLY
为例。在发送端,您的this.restemplate.postForEntity
java对象需要序列化为json,因此它需要用户
,当rest端点接收到json时,它需要将json反序列化为读取
java对象,因此需要用户
。写入
this.restTemplate.getForEntity的情况也一样
- 一种解决方案是在返回之前将
端点上用户的GET
字段设置为nullpassword
- 另一种解决方案是创建一个单独的
无密码字段,并从UserDto
端点返回它GET
- 另一个解决方案是创建两个
s,其中一个有密码,另一个没有密码。然后用正确的JsonView
@JsonView
- 使用
或WRITE\u ONLY
在您的情况下不起作用。原因是http上的一个调用需要两者。让我们以READ\u ONLY
为例。在发送端,您的this.restemplate.postForEntity
java对象需要序列化为json,因此它需要用户
,当rest端点接收到json时,它需要将json反序列化为读取
java对象,因此需要用户
。写入
this.restTemplate.getForEntity的情况也一样
- 一种解决方案是在返回之前将
端点上用户的GET
字段设置为nullpassword
- 另一种解决方案是创建一个单独的
无密码字段,并从UserDto
端点返回它GET
- 另一个解决方案是创建两个
s,其中一个有密码,另一个没有密码。然后用正确的JsonView
@JsonView
@SpringBootTest
或一个@DataJpaTest
将两者结合在一起将不起作用(第一个是完全集成测试,另一个只是基于JPA的部分,那么是哪一个呢?)。JSON又有什么问题?您指定在生成JSON时,密码
字段不应该是JSON的一部分,只有在接收到JSON时才应该是。它基本上完全按照您的要求执行。您可以使用@springbootest
或@DataJpaTest
组合这两个字段都不起作用(第一个是完全集成测试,另一个只是一个基于JPA的部分,那么这是哪一个?)。JSON又有什么问题?您指定在生成JSON时,password
字段不应该是JSON的一部分,只有在接收到JSON时才是。它基本上完全按照您的要求执行。
@SpringBootTest(classes = CardmaniaApplication.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
public class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private IUserRepository userRepository;
@Test
@WithUserDetails("me@example.com")
void registrationWorksThroughAllLayers() throws Exception {
final String email = "newuser@test.com";
final String firstName = "first";
final String lastName = "last";
final String password = "password";
User user = getTestUser(email, password, firstName, lastName, Name.USER);
ResponseEntity<String> responseEntity = this.restTemplate
.postForEntity("http://localhost:" + port + "/api/users", user, String.class);
assertEquals(201, responseEntity.getStatusCodeValue());
final User createdUser = userRepository.findByEmail(email);
assertNotNull(createdUser);
assertNotNull(createdUser.getPassword());
}
@Test
@WithUserDetails("me@example.com")
void getDetailsAboutMyself() throws JsonProcessingException, JSONException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails user = (UserDetails) authentication.getPrincipal();
final User foundUser = userRepository.findByEmail(user.getUsername());
ResponseEntity<String> responseEntity = this.restTemplate
.getForEntity("http://localhost:" + port + "/api/users/" + foundUser.getId(), String.class);
assertEquals(200, responseEntity.getStatusCodeValue());
// assert proper response
final String userAsJson = objectMapper.writeValueAsString(user);
assertEquals(userAsJson, responseEntity.getBody());
JSONObject object = (JSONObject) new JSONTokener(userAsJson).nextValue();
// Verify no password is returned.
assertNull(object.getString("password"));
}
...
}
{"id":null,"firstName":"first","lastName":"last","email":"newuser@test.com","enabled":true,"tokenExpired":false,"roles":null,"username":"newuser@test.com","authorities":null,"accountNonExpired":false,"accountNonLocked":false,"credentialsNonExpired":false}