Spring引导@ResponseBody不会序列化实体ID

Kon*_*tin 89 java spring json spring-boot

有一个奇怪的问题,无法弄清楚如何处理它.有简单的POJO:

@Entity
@Table(name = "persons")
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "middle_name")
    private String middleName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "comment")
    private String comment;

    @Column(name = "created")
    private Date created;

    @Column(name = "updated")
    private Date updated;

    @PrePersist
    protected void onCreate() {
        created = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
        updated = new Date();
    }

    @Valid
    @OrderBy("id")
    @OneToMany(mappedBy = "person", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<PhoneNumber> phoneNumbers = new ArrayList<>();

    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 getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

    public String getLastName() {
        return lastName;
    }

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

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public Date getCreated() {
        return created;
    }

    public Date getUpdated() {
        return updated;
    }

    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

    public void addPhoneNumber(PhoneNumber number) {
        number.setPerson(this);
        phoneNumbers.add(number);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

@Entity
@Table(name = "phone_numbers")
public class PhoneNumber {

    public PhoneNumber() {}

    public PhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "phone_number")
    private String phoneNumber;

    @ManyToOne
    @JoinColumn(name = "person_id")
    private Person person;

    public Long getId() {
        return id;
    }

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

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}
Run Code Online (Sandbox Code Playgroud)

和休息终点:

@ResponseBody
@RequestMapping(method = RequestMethod.GET)
public List<Person> listPersons() {
    return personService.findAll();
}
Run Code Online (Sandbox Code Playgroud)

在json响应中有除Id之外的所有字段,我需要在前端编辑/删除人.如何配置spring boot以序列化Id?

这就是现在响应的样子:

[{
  "firstName": "Just",
  "middleName": "Test",
  "lastName": "Name",
  "comment": "Just a comment",
  "created": 1405774380410,
  "updated": null,
  "phoneNumbers": [{
    "phoneNumber": "74575754757"
  }, {
    "phoneNumber": "575757547"
  }, {
    "phoneNumber": "57547547547"
  }]
}]
Run Code Online (Sandbox Code Playgroud)

UPD有双向hibernate映射,也许它与问题有某种关系.

Pat*_*ard 133

我最近有同样的问题,因为这是spring-boot-starter-data-rest默认情况下的工作原理.见我的SO问题- > 在迁移应用程序到春天开机后使用Spring数据休息时,我观察到,与@Id实体属性不再编组到JSON

要自定义其行为方式,可以扩展RepositoryRestConfigurerAdapter为公开特定类的ID.

import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;

@Configuration
public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(Person.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 并且不要忘记现在为实体类中的 id 支持 getter 和 setter!..(我忘记了它并且为此搜索了很多时间) (4认同)
  • coudnt在`org.springframework.data.rest.webmvc.config`中找到`RepositoryRestConfigurerAdapter` (3认同)
  • 产生:不推荐使用RepositoryRestConfigurerAdapter类型。也似乎不起作用 (2认同)
  • 实际上,`RepositoryRestConfigurerAdapter`在最新版本中已过时,您必须直接实现`RepositoryRestConfigurer`(使用`implements RepositoryRestConfigurer`而不是`extends RepositoryRestConfigurerAdapter`) (2认同)

Nic*_*lau 38

如果您需要公开所有实体的标识符:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;

import javax.persistence.EntityManager;
import javax.persistence.metamodel.Type;

@Configuration
public class RestConfiguration implements RepositoryRestConfigurer {

    @Autowired
    private EntityManager entityManager;

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(
                entityManager.getMetamodel().getEntities().stream()
                .map(Type::getJavaType)
                .toArray(Class[]::new));
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您只想公开扩展或实现特定超类或接口的实体的标识符:

    ...
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(
                entityManager.getMetamodel().getEntities().stream()
                .map(Type::getJavaType)
                .filter(Identifiable.class::isAssignableFrom)
                .toArray(Class[]::new));
    }
Run Code Online (Sandbox Code Playgroud)

如果您只想公开具有特定注释的实体的标识符:

    ...
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(
                entityManager.getMetamodel().getEntities().stream()
                .map(Type::getJavaType)
                .filter(c -> c.isAnnotationPresent(ExposeId.class))
                .toArray(Class[]::new));
    }
Run Code Online (Sandbox Code Playgroud)

示例注释:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExposeId {}
Run Code Online (Sandbox Code Playgroud)

  • 从实体管理器的元模型中添加了很棒的解决方案。 (2认同)
  • @DavidKrider :它应该在它自己的文件中,在_Component Scan_覆盖的任何目录中。主应用程序下的任何子包(带有 `@SpringBootApplication` 注释)应该没问题。 (2认同)

Sal*_*lab 23

来自@ eric-peladan的回答没有开箱即用,但非常接近,可能适用于以前版本的Spring Boot.现在这是它应该如何配置,如果我错了,请纠正我:

import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;

@Configuration
public class RepositoryConfiguration extends RepositoryRestConfigurerAdapter {

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(User.class);
        config.exposeIdsFor(Comment.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 确认此解决方案在Spring Boot v1.3.3.RELEASE下工作正常,与@ eric-peladan提出的解决方案不同. (3认同)

小智 5

该类RepositoryRestConfigurerAdapter自 3.1 起已弃用,RepositoryRestConfigurer直接实现。

@Configuration
public class RepositoryConfiguration implements RepositoryRestConfigurer  {
	@Override
	public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
		config.exposeIdsFor(YouClass.class);
		RepositoryRestConfigurer.super.configureRepositoryRestConfiguration(config);
	}
}
Run Code Online (Sandbox Code Playgroud)

字体:https : //docs.spring.io/spring-data/rest/docs/current-SNAPSHOT/api/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurer.html