我有两个模特:
@Entity
class ModelA {
...
@OneToMany(mappedBy = "modelA")
@JsonManagedReference
private List<ModelB> modelBs = new ArrayList<ModelB>();
...
}
@Entity
class ModelB {
...
@ManyToOne
@JoinColumn(name = "modela_id")
@JsonBackReference
private ModelA modela;
...
}
以及用于ModelA的REST/资源控制器,该控制器具有list方法:
@GetMapping("list")
public @ResponseBody ArrayList<ModelA> list() {
ArrayList<ModelA> modelas = new ArrayList();
for (ModelA moa : modelARepository.findAll()) {
modelas.add(moa);
}
return modelas;
}
现在,默认情况下,来自控制器的响应将包含一个ModelA对象的JSON数组,但这些对象也将包含ModelB。有没有一种方法可以选择您希望序列化的关系以及何时序列化?
来自Django/Laravel,我将使用专用序列化来解决这个问题,例如,我将有一个ModelAWithRelatiionsSerializer
,其中我将序列化ModelA +所有它的关系,或者ModelAWithModelBSerializer
,它将返回使用一个ModelB级别序列化的ModelA,等等。
我知道我可以使用juse忽略注释来不包含它,但这确实不一样,我没有看到任何关于Spring包中序列化的东西。做这件事的最佳或最佳方法是什么?
发布于 2016-12-25 10:49:18
对于来自Laravel(PHP)、Django(Python)、Rails(Ruby)的其他人来说:
我创建了一个包serializers
,在这个包中,我为我的每个模型创建了一个序列化类。
public class UserSerializer {
// Default user values
public interface User {}
// User values with users posts
public interface UserWithPosts extends User {}
}
现在,在您的模型中,您要做的是注释它们属于哪个序列化器的字段:
@Entity
class User {
@Id
@GeneratedValue
@JsonView(UserSerializer.User.class)
private Long id;
@JsonView(UserSerializer.User.class)
private String username;
@JsonView(UserSerializer.User.class)
private String email;
@OneToMany(mappedBy = "user")
@JsonManagedReference // This prevents infinite loop
@JsonView(UserSerializer.UserWithPosts.class)
private List<Post> posts;
// .. getters and setters bellow
}
在您的控制器中,您要用@JsonView(..)
注释您的方法,以说明您希望使用哪个序列化程序。
@RestController
@RequestMapping("users")
public class UsersController {
private UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
/**
* In list method we only want users default values to keep the payload smaller.
*/
@GetMapping("list")
@JsonView(UserSerializer.User.class)
public @ResponseBody ArrayList<User> list() {
ArrayList<User> users = new ArrayList<>();
for (User user : userRepository.findAll()) {
users.add(user);
}
return users;
}
/**
* In this method we are only fetching a single user so payload is smaller so we can add the users posts as well. You could also toggle this with a url filter/parameter.
*/
@GetMapping("show")
@JsonView(UserSerializer.UserWithPosts.class)
public @ResponseBody ArrayList<User> show(@RequestParam(name = "id", required = true) Long id) {
return userRepository.findOne(id):
}
}
Configuration!很容易理解,但是当我第一次这么做的时候,没有一个例子/教程告诉/显示您也需要更新配置。如果您不这样做,那么序列化您的关系就会有问题,但是序列化程序仍然可以工作,但是在您的JSON响应中会得到这样的结果:
...
"posts": [
{},
{},
{},..
]
...
因此,它将为每个post用户返回一个JSON对象,但是没有值来修复我创建的config
包,添加了一个WebConfiguration
类:
@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().defaultViewInclusion(true).build();
converters.add(new MappingJackson2HttpMessageConverter(mapper));
}
}
您也可以在XML配置中这样做。但我个人更喜欢使用基于Java类的配置。如果春天的文档能为新来的人提供更好的解释,那就太好了。
发布于 2022-01-17 23:14:11
拿一个没有那种关系的模型
$this->user = $user->withoutRelations();
https://stackoverflow.com/questions/41308838
复制相似问题