I have following:
@Data
@Entity
@Table(name = "floor")
public class Floor {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "floor_id")
private Long id;
@JsonIgnoreProperties(value= {"floor", "registrations"})
@OneToMany (mappedBy = "floor", cascade = CascadeType.ALL)
private Set<Slot> slots;
}
@Entity
@Table(name = "slot")
public class Slot {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "slot_id")
private Long id;
@ManyToOne
@JoinColumn(name = "floor_id")
private Floor floor;
}
@RestController
public class Controller {
@Autowired
FloorService floorService;
@GetMapping("/api/floors")
public List<Floor> getAllFloors() {
// calls repository.findAll()
return floorService.getAllFloors();
}
}
When accessing API endpoint, I get:
2021-03-06 06:52:30.038 WARN 699889 --- [tp1028811481-19] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]->com.veebzone.parking.model.Floor["slots"])]
By getting list of each floor with /api/floors endpoint, my goal is to get list of slots associated with each floor within their JSON element.
What is the best practice to achieve this:
Using a DTO would be the best, so you can decouple your database classes from the REST API.
If you want the quick solution, you can use Jackson's @JsonManagedReference
and @JsonBackReference
. This will tell Jackson that there's a recursion / bidirectional reference, and how to serialize it:
class Floor {
@JsonManagedReference
Set<Slot> slots;
}
class Slot {
@JsonBackReference
Floor floor;
}
I'm assuming you want something like this (an array of floors, each one with an array of slots) when you call the endpoint:
[
{ "id": 1,
"slots": [
{ "id": 1 },
{ "id": 2 }
]
},
{ "id": 2,
"slots": [
{ "id": 3 }
]
}
]
You have an Infinite recursion because Jackson, the default library used in Spring Boot to write/reads Json (like in your enpoint), tries to use every field in your class to build the Json.
So what is happening is that Jackson is trying to write the first floor in the output Json, but this floor relates to the first slot, which relates to the first floor and so on. There's your loop.
If you want to break the loop you have 2 choices:
Now, which option is better will depend on how large your entities are and how complex the relation between entities will be.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.