Konstantin Konstantin - 9 days ago 6
Java Question

Spring boot @ResponseBody doesn't serialize entity id

Have a strange problem and can't figure out how to deal with it.
Have simple 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?

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.

Answer

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

To customize how it behaves, you can extend RepositoryRestMvcConfiguration to expose IDs for specific classes.

@Configuration
public class RepositoryConfig extends RepositoryRestMvcConfiguration {
    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(Person.class);
    }
}
Comments