【问题标题】:No serializer found when serializing one Object序列化一个对象时未找到序列化程序
【发布时间】:2018-03-19 06:49:14
【问题描述】:

我正在尝试将对象作为 JSON 返回。 使用 /user/id 端点,我想根据用户的 ID 显示用户。 调用此控制器方法时,我得到以下异常:

InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.sample.scrumboard.models.User_$$_jvsta02_1["handler"])

我的控制器类看起来像这样:

@RestController
@RequestMapping(path="/user")
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserRestController {

    private UserRepository repository;

    @Autowired
    public UserRestController(UserRepository repository){
        this.repository = repository;
    }

    @GetMapping(value = "/list")
    public List<User> getUsers(){
        return repository.findAll();
    }

    @GetMapping(value = "/{id}")
    public @ResponseBody User getUserById(@PathVariable Long id, User user){
            user = repository.getOne(id);
            return user;
    }
}

我检查了所有字段是否有公共 getter,并尝试了使用 @JSONIgnoreProperties 的各种选项,但我找不到。 将所有用户显示为 JSONlist 确实适用于带有 /user/list 的 JSONlist。所以问题只存在于尝试显示一个对象而不是对象列表时。 它确实从存储库中找到了用户,但它无法序列化该对象并放在屏幕上。

User 类本身如下所示:

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "userId", nullable = false, updatable = false)
    private Long id;

    @NotNull
    @Size(min=2, max=20)
    private String firstName;

    @NotNull
    @Size(min=2, max=30)
    private String lastName;

    @NotNull
    @Size(min=2, max=20)
    private String userName;

    @NotNull
    @Size(min=2, max=30)
    private String passWord;

    @NotNull
    @Email
    private String email;

    //the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship
    @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonIgnore
    private List<UserStory> userStoryList;

    public User() {
    }

    public User(String firstName, String lastName, String userName, String passWord, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.userName = userName;
        this.passWord = passWord;
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", userName='" + userName + '\'' +
                ", passWord='" + passWord + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public List<UserStory> getUserStoryList() {
        return userStoryList;
    }

    public void setUserStoryList(List<UserStory> userStoryList) {
        this.userStoryList = userStoryList;
    }
}

如何显示从/user/id 返回的用户?

解决方案?

如下所示,我使用 Dto 和 ModelMapper 使其工作。

我加了

@Bean
public ModelMapper modelMapper(){
    return new ModelMapper();
}

控制器方法

@GetMapping(value = "/{id}")
public UserDTO getUserById(@PathVariable Long id, User user, ModelMapper modelMapper){
        user = repository.getOne(id);
        return modelMapper.map(user, UserDTO.class);
}

和 UserDto

public class UserDTO {
    private Long id;
    private String firstName;
    private String lastName;
    private String userName;
    private String passWord;
    private String email;
    private List<UserStory> userStoryList;
    //getters and setters

现在我可以在屏幕上显示一个用户。 我仍然想知道是否没有使用 Jackson 而没有 modelmapper 和 dto 的解决方案?

【问题讨论】:

    标签: java json spring objectmapper


    【解决方案1】:

    也许使用您的实体(用户)通过 REST 公开有关用户的数据不是一个好主意?你可以为你的用户创建 UserDTO 来实现 Serializable 并通过 REST 发送这个 DTO 吗?在这种情况下,应该有必要将从数据库中检索到的 User 对象转换为 UserDTO。

    【讨论】:

    • 好的,我会这样尝试。但是杰克逊不应该不需要创建我自己的 ModelMapper 就可以为我做这件事吗?
    • 很遗憾,我无法回答,因为我对 Spring 的经验非常有限(我主要使用 Java EE)。但据我所知,REST 不应公开数据库中的实体,而应公开您可以控制的 DTO,这是一条经验法则。
    • 这是一个经验法则。不,它通常似乎是作为事实陈述呈现的意见问题。
    【解决方案2】:

    尝试将以下行添加到您的 application.properties 文件中:

    spring.jackson.serialization.fail-on-empty-beans=false

    【讨论】:

      【解决方案3】:

      不要在控制器类中使用@JsonIgnoreProperties(ignoreUnknown = true)

      在实体类中使用下面的注解。那解决了那个问题。

      @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
      

      【讨论】:

        【解决方案4】:

        注解@JsonIgnoreProperties不应该在UserRestController上,需要序列化的是User,去掉注解就可以了。 Jackson 将帮助完成所有工作,如果您想忽略 User 类上的某些字段,请将 @JsonIgnoreProperties 移动到 User 类,并在需要显示在页面上的字段上添加 @JsonProperty

        【讨论】:

        • 好的。那我还得创建一个 DTO 吗?
        【解决方案5】:

        实现 java.io.Serializable 接口的 orm 类的可序列化性

        你使用的是@RestController,不需要@ResponseBody

        另外,也不需要创建一个 DTO 类来为响应 json 转换 ORM 类。

        OBS:对于双向关系,您将使用@JsonManagedReference、@JsonBackReference

        【讨论】:

          【解决方案6】:

          spring repository.getOne() 和 repository.findById() 是有区别的。使用 getOne() 您可以获得参考(代理),例如如果对象已经在同一个事务中被读取。使用 findById(),您总能按预期获得用户。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-07-03
            • 2011-01-24
            • 1970-01-01
            • 1970-01-01
            • 2015-09-18
            • 2017-08-05
            • 2021-07-30
            相关资源
            最近更新 更多