Java Spring boot @ResponseBody 不序列化实体 id
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24839760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring boot @ResponseBody doesn't serialize entity id
提问by Konstantin
Have a strange problem and can't figure out how to deal with it. Have simple POJO:
遇到一个奇怪的问题,不知道如何处理。有简单的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);
}
}
and rest endpoint:
和休息端点:
@ResponseBody
@RequestMapping(method = RequestMethod.GET)
public List<Person> listPersons() {
return personService.findAll();
}
In json response there are all fields except Id, which I need on front end side to edit/delete person. How can I configure spring boot to serialize Id as well?
在 json 响应中有除 Id 之外的所有字段,我需要在前端编辑/删除人员。如何配置 spring boot 以序列化 Id?
That's how response looks like now:
这就是现在的响应:
[{
"firstName": "Just",
"middleName": "Test",
"lastName": "Name",
"comment": "Just a comment",
"created": 1405774380410,
"updated": null,
"phoneNumbers": [{
"phoneNumber": "74575754757"
}, {
"phoneNumber": "575757547"
}, {
"phoneNumber": "57547547547"
}]
}]
UPD Have bidirectional hibernate mapping, maybe it's somehow related to issue.
UPD 有双向休眠映射,也许它与问题有某种关系。
采纳答案by Patrick Grimard
I recently had the same problem and it's because that's how spring-boot-starter-data-rest
works by default. See my SO question -> While using Spring Data Rest after migrating an app to Spring Boot, I have observed that entity properties with @Id are no longer marshalled to JSON
我最近遇到了同样的问题,因为这是spring-boot-starter-data-rest
默认情况下的工作方式。请参阅我的 SO 问题 ->在将应用程序迁移到 Spring Boot 后使用 Spring Data Rest 时,我观察到带有 @Id 的实体属性不再编组为 JSON
To customize how it behaves, you can extend RepositoryRestConfigurerAdapter
to expose IDs for specific classes.
要自定义其行为方式,您可以扩展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);
}
}
回答by Konstantin
Hm, ok seems like I found the solution. Removing spring-boot-starter-data-rest from pom file and adding @JsonManagedReference to phoneNumbers and @JsonBackReference to person gives desired output. Json in response isn't pretty printed any more but now it has Id. Don't know what magic spring boot performs under hood with this dependency but I don't like it :)
嗯,好吧似乎我找到了解决方案。从 pom 文件中删除 spring-boot-starter-data-rest 并将 @JsonManagedReference 添加到 phoneNumbers 并将 @JsonBackReference 添加到 person 提供所需的输出。响应的 Json 不再打印出来,但现在它有 Id。不知道具有这种依赖性的神奇弹簧靴在引擎盖下执行了什么,但我不喜欢它:)
回答by eric peladan
With Spring Boot you have to extends SpringBootRepositoryRestMvcConfiguration
if you use RepositoryRestMvcConfigurationthe configuration define in application.properties may not worked
使用 Spring Boot 你必须扩展SpringBootRepositoryRestMvcConfiguration
如果你使用RepositoryRestMvcConfiguration在 application.properties 中定义的配置可能不起作用
@Configuration
public class MyConfiguration extends SpringBootRepositoryRestMvcConfiguration {
@Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(Project.class);
}
}
But for a temporary need You can use projection to include idin the serialization like :
但是对于临时需要,您可以使用投影在序列化中包含id,例如:
@Projection(name = "allparam", types = { Person.class })
public interface ProjectionPerson {
Integer getIdPerson();
String getFirstName();
String getLastName();
}
}
回答by Salvatorelab
Answer from @eric-peladan didn't work out of the box, but was pretty close, maybe that worked for previous versions of Spring Boot. Now this is how it is supposed to be configured instead, correct me if I'm wrong:
来自@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);
}
}
回答by Андрей Миронов
回答by lcnicolau
In case you need to expose the identifiers for all entities:
如果您需要公开所有实体的标识符:
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));
}
}
Note that in versions of Spring Boot prior to 2.1.0.RELEASE
you must extend the (now deprecated)org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter
instead of implement RepositoryRestConfigurer
directly.
请注意,在之前的 Spring Boot 版本中,2.1.0.RELEASE
您必须扩展(现已弃用)org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter
而不是RepositoryRestConfigurer
直接实现。
If you only want to expose the identifiers of entities that extends or implements specific super class or interface:
如果您只想公开扩展或实现特定超类或接口的实体的标识符:
...
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(
entityManager.getMetamodel().getEntities().stream()
.map(Type::getJavaType)
.filter(Identifiable.class::isAssignableFrom)
.toArray(Class[]::new));
}
If you only want to expose the identifiers of entities with a specific annotation:
如果您只想公开具有特定注释的实体标识符:
...
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(
entityManager.getMetamodel().getEntities().stream()
.map(Type::getJavaType)
.filter(c -> c.isAnnotationPresent(ExposeId.class))
.toArray(Class[]::new));
}
Sample annotation:
示例注释:
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExposeId {}
回答by David B.
@Component
public class EntityExposingIdConfiguration extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
try {
Field exposeIdsFor = RepositoryRestConfiguration.class.getDeclaredField("exposeIdsFor");
exposeIdsFor.setAccessible(true);
ReflectionUtils.setField(exposeIdsFor, config, new ListAlwaysContains());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
class ListAlwaysContains extends ArrayList {
@Override
public boolean contains(Object o) {
return true;
}
}
}
回答by Gisomar Junior
The class RepositoryRestConfigurerAdapter
has been deprecated since 3.1, implement RepositoryRestConfigurer
directly.
该类RepositoryRestConfigurerAdapter
自 3.1 起已弃用,RepositoryRestConfigurer
直接实现。
@Configuration
public class RepositoryConfiguration implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(YouClass.class);
RepositoryRestConfigurer.super.configureRepositoryRestConfiguration(config);
}
}
字体:https: //docs.spring.io/spring-data/rest/docs/current-SNAPSHOT/api/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurer.html