java 序列化一个对象时未找到序列化程序

sczxawaw  于 2023-02-14  发布在  Java
关注(0)|答案(7)|浏览(166)

我尝试以JSON形式返回一个对象。使用/user/id端点,我想根据用户的ID显示用户。调用此controllerMethod时,我遇到以下异常:

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"])

我的contollerClass看起来像这样:

@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);
}

和用户Dto

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和没有模型Map器和dto?

6ju8rftf

6ju8rftf1#

尝试将以下行添加到application.properties文件中:
spring.jackson.serialization.fail-on-empty-beans=false

xmq68pz9

xmq68pz92#

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

6pp0gazn

6pp0gazn3#

不要在控制器类中使用@JsonIgnoreProperties(ignoreUnknown = true)
在实体类中使用下面的注解,这样就解决了这个问题。

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

smtd7mpg4#

注解@JsonIgnoreProperties不应该在UserRestController上,你需要序列化的是User,删除注解就可以了。Jackson会帮助做所有的工作,如果你想忽略类User上的一些字段,将@JsonIgnoreProperties移到User类,并在需要显示在页面上的字段上添加@JsonProperty

tvmytwxo

tvmytwxo5#

实现java.io.Serializable接口的orm类的序列化
您正在使用@RestController,不需要@ResponseBody
此外,不需要创建DTO类来转换响应json的ORM类。
OBS:对于双向关系,您将使用@JsonManagedReference、@JsonBackReference

ekqde3dh

ekqde3dh6#

spring repository.getOne()和repository.findById()之间存在差异。使用getOne(),您可以获取引用(代理),例如,如果对象已经在同一事务中读取。使用findById(),您总是可以按预期获取用户。

wswtfjt7

wswtfjt77#

我在我原因中应用了@JsonIgnoreProperties({“hibernateLazyInitializer”,“handler”})spring.Jackson.serialization.fail-on-empty-beans=false。它没有正常工作。

相关问题