首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >无关系序列化模型

无关系序列化模型
EN

Stack Overflow用户
提问于 2016-12-23 23:15:12
回答 2查看 279关注 0票数 1

我有两个模特:

代码语言:javascript
代码运行次数:0
运行
复制
@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方法:

代码语言:javascript
代码运行次数:0
运行
复制
@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包中序列化的东西。做这件事的最佳或最佳方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-12-25 18:49:18

对于来自Laravel(PHP)、Django(Python)、Rails(Ruby)的其他人来说:

我创建了一个包serializers,在这个包中,我为我的每个模型创建了一个序列化类。

代码语言:javascript
代码运行次数:0
运行
复制
public class UserSerializer {

  // Default user values
  public interface User {}

  // User values with users posts
  public interface UserWithPosts extends User {}  

}

现在,在您的模型中,您要做的是注释它们属于哪个序列化器的字段:

代码语言:javascript
代码运行次数:0
运行
复制
@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(..)注释您的方法,以说明您希望使用哪个序列化程序。

代码语言:javascript
代码运行次数:0
运行
复制
@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响应中会得到这样的结果:

代码语言:javascript
代码运行次数:0
运行
复制
...
"posts": [
  {},
  {},
  {},..
]
...

因此,它将为每个post用户返回一个JSON对象,但是没有值来修复我创建的config包,添加了一个WebConfiguration类:

代码语言:javascript
代码运行次数:0
运行
复制
@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类的配置。如果春天的文档能为新来的人提供更好的解释,那就太好了。

票数 0
EN

Stack Overflow用户

发布于 2022-01-18 07:14:11

拿一个没有那种关系的模型

代码语言:javascript
代码运行次数:0
运行
复制
 $this->user = $user->withoutRelations();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41308838

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档